选择一行及其下一行和上一行

时间:2015-03-10 14:41:15

标签: mysql optimization

情况:

目前我有3个查询:

  1. 首先 - 通过具有排序位置的id获取数据;
  2. 秒 - 按位置1获取数据;
  3. 第三 - 按位置+ 1获取数据。
  4. 我想只有一个查询可以采取"需要一个"如果存在,则按id +上一个和下一个。

    查询:

    第一

    set @position = 0;
    
    SELECT 
    `position` FROM
    (
      SELECT `id`, @position:=@position+1 as `position` FROM {#table}          
      "other_part_of_query"
      ORDER BY `modified_time` DESC
    ) t
    WHERE 
    t.id = '".id."' 
    LIMIT 1
    

    第二和第三

    set @position = 0;
    
    SELECT 
    `id` FROM
    (
      SELECT `id`, @position:=@position+1 as `position` FROM {#table}          
      "other_part_of_query"
      ORDER BY `modified_time` DESC
    ) t
    WHERE 
    t.`position` = '".position."' 
    LIMIT 1
    

3 个答案:

答案 0 :(得分:1)

这很复杂,因为您要按id选择一行,而是按另一个字段modified_time选择相邻的行。

这个想法是使用变量来枚举行。并且,使用另一行来计算您关心的id的值。在子查询中执行此操作,然后选择所需的行:

SELECT t.*
FROM (SELECT `id`,
              @rn := if(@rnid := if(t.id  = '".id."', @rn + 1, @rnid),
                        @rn + 1, @rn + 1
                       ) as rn
      FROM {#table} t       
           "other_part_of_query" cross join
           (select @rn := 0, @rnid := 0) vars
      ORDER BY `modified_time` DESC
     ) t
WHERE rn in (@rnid - 1, @rnid, @rn)

答案 1 :(得分:0)

您可以在where子句中使用额外条件来解决此问题。考虑以下三个条件:

  • 一行必须具有您想要的modified_time。
  • 一行的最大modified_time必须小于您想要的最大值。 (以前的位置)
  • 一行必须具有仍然大于您想要的最小modified_time。 (下一个职位)

试试这个:

SELECT *
FROM myTable
WHERE modified_time = @myParam
   OR modified_time = (SELECT MAX(modified_time ) FROM myTable WHERE modified_time < @myParam)
   OR modified_time = (SELECT MIN(modified_time ) FROM myTable WHERE modified_time > @myParam);

答案 2 :(得分:0)

选择特定行的下一行和上一行

SET @j = 0;
SET @i = 0;
SELECT *
FROM ( 
    SELECT id, col1, col2, ..., @j:=@j+1 AS pos
    FROM `table`
    WHERE  col1=... ORDER BY col1 DESC, col2 ASC
) AS zz
WHERE (    
    SELECT position
    FROM ( 
        SELECT id AS id2, @i:=@i+1 AS position
        FROM `table`
        WHERE  col1=... ORDER BY col1 DESC, col2 ASC
    ) AS zz
    WHERE id2=$currId
)
IN (pos-1, pos, pos+1)