【问题标题】:Get the top n results per group [duplicate]获取每组的前 n 个结果 [重复]
【发布时间】:2015-09-10 07:18:55
【问题描述】:

我正在使用 sql 从按日期分组的表中检索最后 20 行。我想限制它,以便在每个 post_day 组中只选择前 10 行投票 DESC。

SELECT *, DATE(timestamp) as post_day 
FROM stories 
ORDER BY post_day DESC, votes DESC
LIMIT 0, 20

这是表格的样子:

STORYID         TIMESTAMP           VOTES
1               2015-03-10          1
2               2015-03-10          2
3               2015-03-9           5
4               2015-03-9           3

【问题讨论】:

  • 显示一些虚拟数据来证明你到底想要什么

标签: mysql sql


【解决方案1】:

架构

create table stories
(   storyid int auto_increment primary key,
    theDate date not null,
    votes int not null
);

insert stories(theDate,votes) values 
('2015-03-10',1),
('2015-03-10',2),
('2015-03-09',5),
('2015-03-09',3),
('2015-03-10',51),
('2015-03-10',26),
('2015-03-09',75),
('2015-03-09',2),
('2015-03-10',12),
('2015-03-10',32),
('2015-03-09',51),
('2015-03-09',63),
('2015-03-10',1),
('2015-03-10',11),
('2015-03-09',5),
('2015-03-09',21),
('2015-03-10',1),
('2015-03-10',2),
('2015-03-09',5),
('2015-03-09',3),
('2015-03-10',51),
('2015-03-10',26),
('2015-03-09',75),
('2015-03-09',2),
('2015-03-10',12),
('2015-03-10',44),
('2015-03-09',11),
('2015-03-09',7),
('2015-03-10',19),
('2015-03-10',7),
('2015-03-09',51),
('2015-03-09',79);

查询

set @rn := 0, @thedate := '';
select theDate, votes
from 
(
   select storyid, theDate, votes,
      @rn := if(@thedate = theDate, @rn + 1, 1) as rownum,
      @thedate := theDate as not_used
  from stories
  order by theDate, votes desc
) A
where A.rownum <= 10;

结果

+------------+-------+
| theDate    | votes |
+------------+-------+
| 2015-03-09 |    79 |
| 2015-03-09 |    75 |
| 2015-03-09 |    75 |
| 2015-03-09 |    63 |
| 2015-03-09 |    51 |
| 2015-03-09 |    51 |
| 2015-03-09 |    21 |
| 2015-03-09 |    11 |
| 2015-03-09 |     7 |
| 2015-03-09 |     5 |
| 2015-03-10 |    51 |
| 2015-03-10 |    51 |
| 2015-03-10 |    44 |
| 2015-03-10 |    32 |
| 2015-03-10 |    26 |
| 2015-03-10 |    26 |
| 2015-03-10 |    19 |
| 2015-03-10 |    12 |
| 2015-03-10 |    12 |
| 2015-03-10 |    11 |
+------------+-------+
20 rows in set, 1 warning (0.00 sec)

【讨论】:

    【解决方案2】:

    通常您应该对每个组使用 ROW_NUMBER() 来对每个组内的记录进行排序,然后选择带有ROW_NUMBER &lt;= 10 的记录。在 MySQL 中没有 ROW_NUMBER() 聚合函数,但您可以在 MySQL 中使用 User-Defined variables 来模拟 ROW_NUMBER()

    select storyId, post_day , votes
    from (
       select storyId,
              DATE(timestamp) as post_day, 
              votes,
              @num := if(@grp = DATE(timestamp), @num + 1, 1) as row_number,
              @grp := DATE(timestamp) as dummy
      from stories,(select @num := 0, @grp := null) as T
      order by DATE(timestamp) DESC, votes DESC
    ) as x where x.row_number <= 10;
    

    SQLFiddle demo

    还请看: How to select the first/least/max row per group in SQL

    【讨论】:

      猜你喜欢
      • 2021-09-01
      • 2020-08-25
      • 1970-01-01
      • 2013-07-13
      • 1970-01-01
      • 2020-02-04
      相关资源
      最近更新 更多