【问题标题】:Get records from last hour or last 20 items if there is none in the last hour如果过去一小时内没有记录,则获取过去一小时或过去 20 项的记录
【发布时间】:2017-09-23 04:20:43
【问题描述】:

我有一个聊天系统,我想显示过去一小时内发送的消息,但我也想显示最近的 20 条消息,无论它们是多久前发送的。

有没有办法在 SQL 查询中做到这一点?

CREATE TABLE IF NOT EXISTS `chat` (
  `id`        INT(11) UNSIGNED                                                                            NOT NULL AUTO_INCREMENT,
  `user_id`   INT(11) UNSIGNED                                                                            NOT NULL,
  `item_id`   INT(11) UNSIGNED                                                                            NOT NULL,
  `message`   TEXT                                                                                        NOT NULL,
  `recipient` INT(11)                                                                                     NOT NULL DEFAULT '0',
  `type`      ENUM ('message', 'announcement') NOT NULL DEFAULT 'message',
  `channel`   ENUM ('general', 'private')                                              NOT NULL DEFAULT 'general',
  `posted`    DATETIME                                                                                    NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `posted` (`posted`),
  KEY `type` (`type`),
  KEY `channel` (`channel`),
  KEY `recipient` (`recipient`)
)
  ENGINE = MyISAM
  DEFAULT CHARSET = `utf8`
  AUTO_INCREMENT = 2;

【问题讨论】:

  • 显示表的架构。
  • @SloanThrasher 抱歉,添加了架构。只是没想到会有那么大的帮助。
  • 一个简单的ORDER BY posted 限制为 20 就可以了
  • 只是让编写 example.answer 变得更容易。
  • @Fred-ii- 那不是只显示过去一小时内的最后 20 个项目吗?呵呵,我试试。

标签: php mysql node.js


【解决方案1】:

这应该可以解决问题:

(
    select * from chat
    where timestamp > DATE_SUB(now(), interval 1 hour)
)
union
(   
    select * from chat order by posted desc limit 20
)
order by posted

解释:

  • 它会选择过去一小时内的所有消息。
  • 它还选择最后 20 条消息,作为单独的查询(20 条记录很快)
  • 联合合并两个结果,并删除双精度,以防两者重叠

因此,当过去一小时内没有数据时,您仍会获得 20 个最新帖子。如果过去一小时内有大量数据,您将获得所有这些数据。

【讨论】:

  • 这太棒了!谢谢
【解决方案2】:

试试这个:

SELECT *
FROM `chat`
ORDER BY `posted` DESC
LIMIT 0,20;

它将列出最后 20 行(按日期/时间)。由于您希望在过去一小时内没有足够的聊天记录时使用较旧的聊天记录,因此您无需担心聊天记录的时间。

以下内容未经测试,可能存在语法错误,因此您可能需要稍微尝试一下。

SELECT *
FROM `chat`
WHERE DATE_ADD(a.`posted` interval 1 hour) <= NOW()
UNION
(
    SELECT *
    FROM `chat`
    WHERE a.posted > DATE_SUB(NOW(), interval 1 hour)
    AND (SELECT count(*) FROM `chat` WHERE a.posted <= DATE_SUB(NOW(), interval 1 hour)) < 20
    ORDER BY `posted` DESC
    LIMIT 0,20)
ORDER BY `posted` DESC

只有在过去一小时内的帖子少于 20 条时,才应添加上一小时之前的帖子。

【讨论】:

  • 那不是只显示最后 20 条消息吗?如果过去一小时内发送了 100 条消息怎么办?我想显示所有 100 条消息。
  • 是的,它只显示最后 20 个。我可以重写以显示最后一个小时内的所有内容,加上一个小时内的最后 20 个,您可以在调用查询的代码中忽略它们当您在最后一个小时内有足够的时间时。
  • 只是一个提示:不要这样做DATE_ADD(a.posted interval 1 hour) &lt;= NOW()。相反,请执行a.posted &gt; DATE_SUB(NOW(), interval 1 hour)。它会产生相同的结果,但运行速度要快得多。您的版本需要为表中的每一行添加一个小时,这意味着也不会使用任何索引。那会慢很多。在大桌子上,这将是一个不同的世界。
猜你喜欢
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 2019-05-21
  • 1970-01-01
相关资源
最近更新 更多