1

我想获得每个 4 的最新日期symbolid我在这里修改了代码如下:

set @num := 0, @symbolid := '';
select symbolid, date,
@num := if(@symbolid = symbolid, @num + 1, 1) as row_number,
@symbolid := symbolid as dummy
from projections
group by symbolid, date desc
having row_number < 5

并得到以下结果:

symbolid                date   row_number   dummy       
1       '2011-09-01 00:00:00'       1       1
1       '2011-08-31 00:00:00'       3       1
1       '2011-08-30 00:00:00'       5       1
2       '2011-09-01 00:00:00'       1       2
2       '2011-08-31 00:00:00'       3       2
2       '2011-08-30 00:00:00'       5       2
3       '2011-09-01 00:00:00'       1       3
3       '2011-08-31 00:00:00'       3       3
3       '2011-08-30 00:00:00'       5       3
4       '2011-09-01 00:00:00'       1       4
...

显而易见的问题是,为什么我每次只得到 3 行symbolid,为什么它们的编号是 1、3、5?一些细节:

  1. 我尝试了强制索引而不是强制索引(如此处所示),并且两种方式都得到了相同的结果。
  2. 日期是正确的,即列表正确显示了前 3 个日期symbolid,但 row_number 值关闭
  3. 当我不使用“有”语句时,行号是正确的,即最近的日期是 1,下一个最近的日期是 2,等等

显然row_number计算字段受到“有”子句的影响,但我不知道如何修复它。

我意识到我可以将“拥有”更改为“拥有 row_number < 7”(6 与 5 相同),但它非常难看,我想知道如何让它“表现”。

4

3 回答 3

2

我不是 100% 确定它为什么会这样(也许是因为逻辑上SELECT是在 之前处理的ORDER BY),但它应该按预期工作:

SELECT * 
FROM 
(
    select symbolid, date,
    @num := if(@symbolid = symbolid, @num + 1, 1) as row_number,
    @symbolid := symbolid as dummy
    from projections
    INNER JOIN (SELECT @symbolid:=0)c
    INNER JOIN (SELECT @num:=0)d
    group by symbolid, date desc

) a
WHERE row_number < 5
于 2011-09-02T15:52:09.907 回答
1

用户定义的变量不能很好地工作,(参考这里

作为一般规则,您永远不应为用户变量赋值并在同一语句中读取该值。您可能会得到预期的结果,但这不能保证。涉及用户变量的表达式的求值顺序是未定义的,并且可能会根据给定语句中包含的元素而改变;此外,不保证此顺序在 MySQL 服务器的版本之间是相同的。在 SELECT @a, @a:=@a+1, ... 中,您可能认为 MySQL 会先评估 @a,然后再进行赋值。但是,更改语句(例如,通过添加 GROUP BY、HAVING 或 ORDER BY 子句)可能会导致 MySQL 选择具有不同评估顺序的执行计划。

这是我的建议

select symbolid, 
substring_index(group_concat(date order by date desc), ',', 4) as last_4_dates
from projections
group by symbolid

这种方法的缺点是它会将日期分组折叠,
并且您需要先分解才能真正使用它。

于 2011-09-02T15:49:40.320 回答
0

最终代码:

set @num := 0, @symbolid := '';
select d.* from
(
select symbolid, date,
  @num := if(@symbolid = symbolid, @num + 1, 1) as row_number,
  @symbolid := symbolid as dummy
from projections
order by symbolid, date desc
 ) d
where d.row_number < 5
于 2011-09-02T16:06:32.407 回答