MYSQL查询获取给定行附近的'n'行

时间:2011-02-14 20:31:53

标签: sql mysql

我有一个名为'videos'的MySQL表,其中一列是'cat'(INT),'id'是PRIMARY KEY。

所以,如果'x'是行号,'n'是类别ID,我需要附近 15行

案例1:'x'之前和之后的类别中有很多行。只需在'x'之前和之后获得7行

SELECT * FROM videos WHERE cat=n AND id<x ORDER BY id DESC LIMIT 0,7
SELECT * FROM videos WHERE cat=n AND id>x LIMIT 0,7

案例2:如果'x'在表的开头/结尾 - &gt;打印所有(假设'y'行)'x'之前/之后的行,然后在'x'之后/之前打印15-y行

案例1不是问题,但我遇到了案例2.是否有任何通用方法可以在'x'行附近获得'p'行?

1 个答案:

答案 0 :(得分:5)

此查询将始终将N(精确id匹配)置于数据的中心,除非没有更多行(在任一方向上),在这种情况下,行将根据需要从前一部分或下一部分添加,而仍保留前/后的数据(尽可能多)。

set @n := 28;

SELECT * FROM
(
SELECT * FROM
(
    (SELECT v.*, 0 as prox  FROM videos v WHERE cat=1 AND id = @n)
    union all
    (SELECT v.*, @rn1:=@rn1+1 FROM (select @rn1:=0) x, videos v WHERE cat=1 AND id < @n ORDER BY id DESC LIMIT 15)
    union all
    (SELECT v.*, @rn2:=@rn2+1 FROM (select @rn2:=0) y, videos v WHERE cat=1 AND id > @n ORDER BY id LIMIT 15)
) z
ORDER BY prox
LIMIT 15
) w
order by id

例如,如果cat = 1有30个id,而你正在查看项目#28,它将显示项目16到30,#28是从底部开始的第3行。

一些解释:

SELECT v。*,0代理 FROM视频v WHERE cat = 1 AND id = @n

  • v。* 表示选择表/别名v中的所有列。在这种情况下, v 是表视频
  • 0作为代理表示创建名为 prox 的列,它只包含值 0

下一个查询:
SELECT v。*,@ rn1:= @ rn1 + 1 FROM (选择@ rn1:= 0)x ,视频v {{ 1}} cat = 1 AND id&lt; @n WHERE id DESC ORDER BY 15

  • v。* - 如上所述
  • @ rn1:= @ rn1 + 1 使用变量返回此子查询中每条记录的序列号。它从1开始,对于每条记录,在LIMIT之后,它将编号为2,然后是3等。
  • (选择@ rn1:= 0)x 这会创建一个别名为 x 的子查询,它所做的就是确保变量 @ rn1 从第一行的值1开始。

最终结果是变量和 0作为代理 ORDER BY id DESC每行基于它与值 @n 的接近程度。条款ranks取最接近N的15个。