Select 一行及其下一行和上一行
Select a row along with its next and previous rows
情况:
目前我有3个问题:
- First - 通过id获取排序位置的数据;
- 其次-按position-1获取数据;
- 第三-按位置+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)
情况:
目前我有3个问题:
- First - 通过id获取排序位置的数据;
- 其次-按position-1获取数据;
- 第三-按位置+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)