为每个日期选择行的子集

时间:2015-01-22 15:08:58

标签: mysql sql greatest-n-per-group

我在MySQL数据库中有一个表,其中包含事件。

我需要选择一个月的活动(例如从12月10日到1月10日),每天限制5个活动。 (事件时间存储为时间戳)。

我可以使用一个查询实现此功能,还是必须启动30个不同的查询?

1 个答案:

答案 0 :(得分:0)

好像你想要greatest_n_per_group。这个网站上有一个tag

对于此示例,在每天有超过5个事件的情况下,您没有指定要选择的5个事件。对于我的例子,让我们考虑你想要选择当天5个最高id的事件。我将以下内容运行到SQL Fiddle:

CREATE TABLE events(
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  eventDate DATE);

INSERT INTO events (eventDate) VALUES ('2014-12-10');
INSERT INTO events (eventDate) VALUES ('2014-12-10');
INSERT INTO events (eventDate) VALUES ('2014-12-10');
INSERT INTO events (eventDate) VALUES ('2014-12-10');
INSERT INTO events (eventDate) VALUES ('2014-12-10');
INSERT INTO events (eventDate) VALUES ('2014-12-10');
INSERT INTO events (eventDate) VALUES ('2014-12-15');
INSERT INTO events (eventDate) VALUES ('2014-12-15');
INSERT INTO events (eventDate) VALUES ('2014-12-15');
INSERT INTO events (eventDate) VALUES ('2014-12-15');
INSERT INTO events (eventDate) VALUES ('2014-12-15');
INSERT INTO events (eventDate) VALUES ('2014-12-20');
INSERT INTO events (eventDate) VALUES ('2014-12-20');
INSERT INTO events (eventDate) VALUES ('2014-12-20');

如果你计算过,12/10(id 1-6)发生了6个事件,12/15(id 7-11)发生了5个事件,12月20日发生了3个事件(id 12-14)。

根据我的预期输出,我应该只看到12月10日事件的ids 2-6,以及其他两天的所有事件。这可以通过以下查询来完成:

SELECT *
FROM events e
WHERE (SELECT COUNT(*)
       FROM events ev
       WHERE ev.eventDate = e.eventDate AND ev.id >= e.id) <= 5
  AND e.eventDate BETWEEN '2014-12-10' AND '2015-01-10';

这类似于自联接,查看每个日期,并通过选择最大id(由条件ev.id >= e.id完成)进行过滤,只要每个日期的行数不超过5

以下是SQL Fiddle示例。