MySql 选择日期相差 30 分钟的行

Posted

技术标签:

【中文标题】MySql 选择日期相差 30 分钟的行【英文标题】:MySql Select rows with 30 minutes difference in date 【发布时间】:2020-04-04 11:25:49 【问题描述】:

我有一个 mysql-8.0/MariaDb-10.4 表,其中包含不同访问者的站点访问列表:

我想创建一个查询,返回每次访问会话第一次访问,其中会话定义是CreatedAt 日期为 30 分钟或更长时间的位置以前的访问。

所以在我的情况下,我应该返回第 2 行(Id 列)、第 8 行和第 13 行。另请注意,会话可以超过 30 分钟,只要每次访问都在少于 30 分钟的情况下成功.

我的解决方案如下:

    SELECT DISTINCT a.`CreatedAt`
    FROM  activities AS a
    LEFT JOIN  activities AS b
    ON ( 
        (UNIX_TIMESTAMP(b.`CreatedAt`)  >= (UNIX_TIMESTAMP(a.`CreatedAt`) - (30 * 60)) ) AND 
        (b.`CreatedAt` < a.`CreatedAt`)
    )
    WHERE (b.`CreatedAt` IS NULL) AND (a.`VisitorId` = '26924c19-3cd1-411e-a771-5ebd6806fb27' /* or others for example */ )

它工作正常,但它不返回最后一行 13,我也不确定这是最好的解决方案。提前致谢。

【问题讨论】:

【参考方案1】:

解决此问题的最简单方法是将所有访问与其早期兄弟姐妹相关联,然后仅选择那些没有的兄弟姐妹。如果不存在以后的访问(如您的 ID 为 13 的示例),则具有 later 兄弟的(更直观的)其他方法将失败。

SELECT
  late.*
FROM activities AS late
LEFT JOIN activities AS early
  ON late.VisitorId=early.VisitorId
  AND late.CreatedAt>early.CreatedAt
  AND late.CreatedAt<=DATE_ADD(early.CreatedAt, INTERVAL +30 MINUTE)
WHERE early.Id IS NULL
-- Maybe: AND late.VisitorId='26924c19-3cd1-411e-a771-5ebd6806fb27'
-- Maybe: ORDER BY late.CreatedAt

【讨论】:

如果我想构建查询以返回每个访问会话的 last 访问,而不是第一次访问,那么将为会话返回第 12 行(8 ,9,10,11,12) 这将再次造成您所处的情况:在任何时间点,当前会话是否仍在进行中或已经结束,都是未知的。过去事件的数据库无法展望未来。您可以尝试自行加入以查找给定查询选择的每个会话的最后一次访问。 引导窗口函数在这个***.com/questions/61443546/…中被证明是非常有用的【参考方案2】:

我对@Eugen Rieck https://***.com/a/61027502/625144 有类似的回答。但是使用MySQLTIMESTAMPDIFF函数

SELECT a.*, 
FROM activities a
LEFT JOIN activities b
    ON b.VisitorId = a.VisitorId
        AND a.Id > b.Id
        AND TIMESTAMPDIFF(MINUTE, b.CreatedAt, a.CreatedAt) <= 30
WHERE
    b.Id IS NULL
;

【讨论】:

以上是关于MySql 选择日期相差 30 分钟的行的主要内容,如果未能解决你的问题,请参考以下文章

从彼此相差不超过 x 分钟的日期中选择最晚的日期

如何在php/codeigniter或mysql中获得两个相差20分钟的日期的所有组合

Mysql按日期时间的日期部分分组,并为每个日期选择具有最大日期时间的行

MySql计算两日期时间之间相差的天数,秒数,分钟数,周数,小时数

怎样得出sql中日期差

Mysql 查询以选择有或没有日期的行