Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql限制每个组的行数_Mysql_Group By_Having_Having Clause - Fatal编程技术网

Mysql限制每个组的行数

Mysql限制每个组的行数,mysql,group-by,having,having-clause,Mysql,Group By,Having,Having Clause,我想得到每个符号的最新4个日期。我修改了代码如下: 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 一个明显的

我想得到每个符号的最新4个日期。我修改了代码如下:

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
一个明显的问题是,为什么我每个符号只得到3行,为什么它们编号为1,3,5?一些细节:

我尝试了两种方法,一种是强制索引,另一种是不强制索引,两种方法都得到了相同的结果。 日期是正确的,即列表正确显示了每个symbolid的前3个日期,但行数值为off 当我不使用having语句时,行号是正确的,即最近的日期是1,下一个最近的日期是2,以此类推 显然,行数计算字段受到having子句的影响,但我不知道如何修复它


我意识到我可以将行数改为行数<7 6与行数5相同,但这非常难看,我想知道如何使其正常工作。

用户定义的变量工作不正常,请参阅

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

这是我的建议

select symbolid, 
substring_index(group_concat(date order by date desc), ',', 4) as last_4_dates
from projections
group by symbolid
这种方法的缺点是它会在日期之前导致集团崩溃,
您需要在实际使用它之前进行分解。

我不能100%确定它为何会以这种方式运行,可能是因为逻辑选择是在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
最终代码:

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

这样做有效,只需将内部查询中的GROUPBY更改为ORDERBY。谢谢我看到你扩展了你的代码。就我而言,我不必把它弄得像你的新例子那样复杂。下面是我的答案,灵感来自你原来的帖子。是的,我明白了。我将变量的定义放入联接中,以避免发出第二个查询集@num:=0,@symbold:=;
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