将组中的日期数据分组

时间:2013-09-02 00:37:35

标签: mysql sql group-by pagination sql-order-by

我有一个看起来像这样的表:

create (DATETIME) |   Message (TEXT)
=========================================
2013-08-05 9:00:00  "Hi there!"
2013-08-05 10:00:00 "Hi again!"
2013-08-07 14:00:00 "Hi from the future!"

我希望能够在DATE(create)上获取所有邮件和群组,以便邮件按2013-08-052013-08-07分组,依此类推。这可以通过ORDER BY

轻松完成
SELECT * FROM messages ORDER BY create

问题是我希望能够按组分页。例如,如果我有10个不同的日期,我想显示所有消息每页5个日期组和分页。

我已经看到很多LIMIT组内元素数量的解决方案,但没有看到LIMIT组数量的任何解决方案。

我基本上会喜欢这样的结果:

如果LIMIT只显示1组:

2013-08-05 9:00:00  "Hi there!"
2013-08-05 10:00:00 "Hi again!"

如果LIMIT显示2组:

2013-08-05 9:00:00  "Hi there!"
2013-08-05 10:00:00 "Hi again!"
2013-08-07 14:00:00 "Hi from the future!"

如果LIMIT显示1组跳过第一组:

2013-08-07 14:00:00 "Hi from the future!"

如何在SQL中实现这一目标?

3 个答案:

答案 0 :(得分:0)

我认为您需要计算组ID并手动执行limit

SELECT m.*
FROM messages m join
     (select date(create) as createdate, count(*) as cnt, @rn := @rn + 1 as groupnum
      from messages m cross join (select @rn := 0) const
      group by date(create)
     ) md
     on date(m.create) = createdate
WHERE groupnum between 1 and 5;

答案 1 :(得分:0)

你可以这样做

  

LIMIT仅显示1个组:

SELECT created, message
  FROM messages m JOIN 
(
  SELECT MIN(created) min_created, MAX(created) max_created
    FROM
  (
    SELECT DATE(created) created
      FROM messages
     GROUP BY DATE(created)
     LIMIT 1 -- use LIMIT as you would normally do here
  ) z
) q
    ON m.created BETWEEN q.min_created AND q.max_created + INTERVAL 1 DAY;

输出:

+---------------------+-----------+
| created             | message   |
+---------------------+-----------+
| 2013-08-05 9:00:00  | Hi there! |
| 2013-08-05 10:00:00 | Hi again! |
+---------------------+-----------+
  

LIMIT显示1个小组跳过第一个小组:

SELECT  created, message
  FROM messages m JOIN 
(
  SELECT MIN(created) min_created, MAX(created) max_created
    FROM
  (
    SELECT DATE(created) created
      FROM messages
     GROUP BY DATE(created)
     LIMIT 1, 1 -- use LIMIT as you would normally do here
  ) z
) q
    ON m.created BETWEEN q.min_created AND q.max_created + INTERVAL 1 DAY;

输出:

+---------------------+---------------------+
| created             | message             |
+---------------------+---------------------+
| 2013-08-07 14:00:00 | Hi from the future! |
+---------------------+---------------------+

注意:确保您在created列上有索引

这是 SQLFiddle 演示

答案 2 :(得分:0)

示例数据更清晰:)

查询#1:从0开始计数的组

SELECT m1.* FROM messages m1 JOIN (
  SELECT DISTINCT date(created) OnlyDate FROM messages
  ORDER BY OnlyDate
  LIMIT 0,1
) m2 ON date(m1.created) = OnlyDate;

|             CREATED |   MESSAGE |
|---------------------|-----------|
|  2013-08-05 9:00:00 | Hi there! |
| 2013-08-05 10:00:00 | Hi again! |

查询#2:1组从1开始计算

SELECT m1.* FROM messages m1 JOIN (
  SELECT DISTINCT date(created) OnlyDate FROM messages
  ORDER BY OnlyDate
  LIMIT 1,1
) m2 ON date(m1.created) = OnlyDate

|             CREATED |             MESSAGE |
|---------------------|---------------------|
| 2013-08-07 14:00:00 | Hi from the future! |

您只需使用limit子句处理组(第一个值是起始组,第二个值是偏移量)。查询也应该非常有效,也不难读。

小提琴here