0

我有两个 MySQL 表:stats(左)和 messages(右)

  +------------+---------+      +---------+------------+-----------+----------+
  |  _date     | msgcount|      | msg_id  | _date      | time      |  message |
  +------------+---------+      +----------------------+-----------+----------+
  | 2011-01-22 |  2      |      |   1     | 2011-01-22 |  06:23:11 | foo bar  |
  | 2011-01-23 |  4      |      |   2     | 2011-01-22 |  15:17:03 | baz      |
  | 2011-01-24 |  0      |      |   3     | 2011-01-22 |  17:05:45 | foobar   |
  | 2011-01-25 |  1      |      |   4     | 2011-01-22 |  23:58:13 | barbaz   |
  +------------+---------+      |   5     | 2011-01-23 |  00:06:32 | foo foo  |
                                |   6     | 2011-01-23 |  13:45:00 | bar foo  |
                                |   7     | 2011-01-25 |  02:22:34 | baz baz  |
                                +---------+------------+-----------+----------+

我填写了 stats.msgcount,但实际上它仍然是空的。我正在寻找一种查询方式:

  • 计算每个 stats._date 的消息数量(注意 2011-01-25 上的零 msgcount)
  • messages.time 是 24 小时格式。5 点(17:00:00)之后的所有消息都应计入第二天(注意 msg_id 3 和 4 计入 2011-01-23)
  • 更新 stats.msgcount 以保存所有计数

我特别关心“晚于 17:00:00 计入次日”部分。这在(My)SQL 中可能吗?

4

2 回答 2

3

你可以使用:

UPDATE stats LEFT JOIN
  ( SELECT date(addtime(_date,time) + interval 7 hour) as corrected_date, 
           count(*) as message_count
    FROM messages
    GROUP BY corrected_date ) mc
ON stats._date = mc.corrected_date
SET stats.msgcount = COALESCE( mc.message_count, 0 )

但是,此查询要求您感兴趣的日期已经在 stats 表中,如果您没有它们,则将 _date 设为主键或唯一键(如果还没有)并使用:

INSERT IGNORE INTO stats(_date,msgcount)
SELECT date(addtime(_date,time) + interval 7 hour) as corrected_date,
       count(*) as message_count
FROM messages
GROUP BY corrected_date
于 2012-04-07T00:20:08.200 回答
1

真的,你所做的只是将时间移动了 7 个小时。像这样的东西应该工作:

UPDATE stats s
SET count = (SELECT COUNT(msg_id) FROM messages m
             WHERE m._date BETWEEN DATE_SUB(DATE_ADD(s._date, INTERVAL TIME_TO_SEC(m.time) SECOND), INTERVAL 7 HOUR)
                               AND DATE_ADD(DATE_ADD(s._date, INTERVAL TIME_TO_SEC(m.time) SECOND), INTERVAL 17 HOUR));

基本思想是,它获取统计表中的每个日期,将其调整 7 小时,然后查找在该范围内发送的消息。如果您使用 DATETIME 列而不是单独的 DATE 和 TIME 列,则不需要额外的 DATE_ADD(..., TIME_TO_SEC) 东西。

可能有更好的方法来添加日期和时间,我没有看到快速浏览 MySQL 参考文档的方法。

因此,您需要做的就是在 stats 表中插入一个新行,其中 msgcount 为 0,然后运行更新命令。如果您只想更新几天(因为消息计数可能在 6 天后不会改变),您只需要在更新中添加一个简单的 where 子句:

UPDATE stats s
SET ...
WHERE s._date BETWEEN '2012-04-03' AND '2012-04-08'
于 2012-04-07T00:21:02.383 回答