为每个日期选择行的子集

Selecting a subset of rows for each date

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

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

我可以用一个查询来实现吗?还是我必须启动 30 个不同的查询?

您似乎想要 greatest_n_per_group。此站点上有一个 tag

对于此示例,如果每天有超过 5 个事件,您没有指定要 select 哪 5 个事件。对于我的示例,假设您想要 select 当天具有 5 个最高 ID 的事件。我把运行下面改成SQLFiddle:

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 日发生了 5 起事件(ID 7-11),12 月 20 日发生了 3 起事件(ID 12-14)。

根据我的预期输出,对于 12 月 10 日的事件,我应该只会看到 ID 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';

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

这是一个 SQL Fiddle 示例。