选择具有特定行号值的行

时间:2014-06-11 21:56:04

标签: mysql having-clause

这是一个包含20个项目的测试表。

create table test (id int not null primary key);
insert into test values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19);

我可以像这样添加一个行号列(小提琴:http://sqlfiddle.com/#!2/dade4/3):

select id, @r:=@r+1 r
from test a
join (select @r:=0) b;

然后我尝试使用HAVING子句获取前10个项目(小提琴:http://sqlfiddle.com/#!2/dade4/4):

select id, @r:=@r+1 r
from test a
join (select @r:=0) b
having r <= 10;

这是意想不到的结果:

ID| R
------
0 | 2
1 | 4
2 | 6
3 | 8
4 | 10

为什么会这样,以及如何检索r在1到10之间的行?

(我没有使用LIMIT,因为在不同的查询中,我需要为每个类别选择前n项)

3 个答案:

答案 0 :(得分:1)

除非您在汇总(HAVINGSUM()COUNT())查询中,否则

GROUP BY没有任何意义。

您需要将rownumbering封装在适当的子查询中(http://sqlfiddle.com/#!2/dade4/6/0)。

select id, r
   from (select id, @r:=@r+1 r
         from test a
         join (select @r:=0) b
   ) as q
where r <= 10;

答案 1 :(得分:1)

当我回答这个问题时,我遇到了类似的问题:

Mysql: Gap detection query not detecting gaps

MySQL显然执行HAVING测试,因为当没有进行聚合时会生成结果,这会导致一些短路。

解决方案是使用子查询。

select id, r
   from (select id, @r:=@r+1 r
         from test a
         join (select @r:=0) b
   ) as q
where r <= 10;

答案 2 :(得分:1)

我同意其他答案,having不是这样,但如果你需要使用它,那么:

select id, @r:=@r+1 r
  from test a
  join (select @r:=0) b
having @r+1 <= 10;

这里是demo in SQLFiddle

你得到错误结果的原因是因为MySql评估别名r的两倍(在select和in中),所以@r:=@r+1执行两次。