【问题标题】:Paginating date data in groups分组日期数据分页
【发布时间】:2013-09-05 00:52:23
【问题描述】:

我有一张如下所示的表格:

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组数量的任何解决方案。

我基本上想要这样的结果:

如果LIMITing 只显示 1 组:

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

如果LIMITing 显示 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!"

如果LIMITing 显示 1 组跳过第一个:

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

这在 SQL 中如何实现?

【问题讨论】:

  • I would like to be able to get all messages and group => 你这是什么意思?你能提供你预期的输出吗?
  • @MostyMostacho 问题已更新:)

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


【解决方案1】:

示例数据更清楚:)

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

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! |

您只需使用限制子句处理组(第一个值是起始组,第二个值是它的偏移量)。查询也应该非常高效,而且也不难阅读。

小提琴here.

【讨论】:

    【解决方案2】:

    我认为您需要计算组 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;
    

    【讨论】:

      【解决方案3】:

      你可以这样做

      LIMITing 只显示 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;
      

      输出:

      +---------+------------+ |创建 |留言 | +---------+------------+ | 2013-08-05 9:00:00 |你好呀! | | 2013-08-05 10:00:00 |你好,我们又见面了! | +---------+------------+

      LIMITing 显示 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;
      

      输出:

      +------------------+----------+ |创建 |留言 | +------------------+----------+ | 2013-08-07 14:00:00 |来自未来的你好! | +------------------+----------+

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

      这里是SQLFiddle演示

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-19
        • 2016-04-23
        • 2016-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多