Select 一行及其下一行和上一行

Select a row along with its next and previous rows

情况:

目前我有3个问题:

  1. First - 通过id获取排序位置的数据;
  2. 其次-按position-1获取数据;
  3. 第三-按位置+1获取数据。

我只想有 1 个查询,它可以 "needed one" by id + previous and next ones if they exists.

查询:

第一个

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

您可以在 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);

这很复杂,因为您 select 按 id 排列一行,但按另一个字段 modified_time 选择相邻的行 modified_time

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

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)

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

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)