我有一个包含日期时间列表的表。
我想找到连续日期之间的最长时间,即,找到时间轴上彼此相邻的任何两个日期时间条目之间的最大距离。把它想象成“最长条纹” - 从一个重置到下一个按时间顺序排列的最长时间。
例如:
mysql> select * from resets order by datetime asc;
+----+---------------------+-------------+---------------------+---------------------+
| id | datetime | activity_id | created_at | updated_at |
+----+---------------------+-------------+---------------------+---------------------+
| 7 | 2014-12-30 20:38:22 | 1 | 2015-01-06 20:38:22 | 2015-01-06 20:38:22 |
| 3 | 2014-12-31 20:38:22 | 1 | 2015-01-06 20:38:22 | 2015-01-06 20:38:22 |
| 5 | 2015-01-01 20:38:22 | 1 | 2015-01-06 20:38:22 | 2015-01-06 20:38:22 |
| 4 | 2015-01-02 20:38:22 | 1 | 2015-01-06 20:38:22 | 2015-01-06 20:38:22 |
| 6 | 2015-01-03 20:38:22 | 1 | 2015-01-06 20:38:22 | 2015-01-06 20:38:22 |
| 1 | 2015-01-04 20:38:22 | 1 | 2015-01-06 20:38:22 | 2015-01-06 20:38:22 |
| 2 | 2015-01-05 20:38:22 | 1 | 2015-01-06 20:38:22 | 2015-01-06 20:38:22 |
etc...
从上面的示例数据集中,我想知道以下哪个时间差异更大:
(显然,它们相隔24小时。我正在寻找一般的解决方案。)
通过迭代有序数组,存储连续值之间的差异,并选择最大值,可以使用普通编程语言轻松完成。
使用仅 SQL吗?
有一种巧妙的方法吗?更新
对我有用的查询是
SELECT MAX(DATEDIFF(r.next_datetime, r.datetime))
FROM (
# finds each datetime and the next consecutive one in the table
SELECT r1.datetime as datetime, (
# finds the next consecutive datetime
SELECT datetime
FROM resets r2
WHERE r2.datetime > r1.datetime
ORDER BY datetime ASC
LIMIT 1
) as next_datetime
FROM resets as r1
ORDER BY r1.datetime
) as r;
最里面的查询SELECT datetime FROM resets r2...
负责查找列表中的下一个日期时间,该日期时间大于当前日期时间。请注意,此查询是有序的,并且限制为1.这对我来说是最难的部分。
其余的非常简单。对于表中的每一行,我们在表中选择日期时间值和下一个连续日期时间。最外层的查询找到我们刚刚创建的任何日期时间对之间的最大差异 - “连胜”。
我选择了@OllieJones给出的答案,因为它是最好的和最好的解释,即使我更喜欢“纯SQL”解决方案。
答案 0 :(得分:5)
此查询将计算连续行之间的时间差异并显示最大的一行 - 连胜的长度。如果你需要整行,你需要戈登的询问。
SELECT MAX(diff)
FROM (
SELECT TIMEDIFF(datetime,@prev) AS diff,
(@prev:=datetime) AS datetime
FROM resets,
(SELECT @prev:=(SELECT MIN(datetime) FROM resets)) AS init
ORDER BY datetime
) AS diffs
这是如何运作的?
首先,它是一行查询与您的表之间的交叉连接。单行查询是这样的:
(SELECT @prev:=(SELECT MIN(datetime) FROM resets))
它将用户定义的值@prev
设置为表格中最低/最早datetime
。这是在查询开始时初始化用户定义变量的MySQL技巧。
然后,SELECT子句中有两列:
SELECT TIMEDIFF(datetime,@prev) AS diff,
(@prev:=datetime) AS datetime
第一个获取当前行datetime
与@prev
的值之间的时差。第二个将@prev
的值更新为当前行datetime
。
因此内部查询会在ORDER BY datetime
中显示时间戳列表以及与前一个时间戳的差异。
外部查询SELECT MAX(diff)
从内部查询中获取diff的最大值 - 最长连胜 -
让我们明确一点:这是特定于MySQL的猴子业务。纯SQL应该是声明性的,而不是程序性的。但是,使用用户定义的@prev
变量的这个技巧可以让我们以有用的方式混合声明性和过程性代码,即使它有点模糊。
答案 1 :(得分:3)
您可以使用相关子查询计算下一个日期时间,然后通过排序找到最大值:
select r.*
from (select r.*,
(select datetime
from resets r2
where r2.datetime > r.datetime
order by datetime
limit 1
) as next_datetime
from resets r
) r
order by timestampdiff(second, datetime, next_datetime) desc
limit 1;
答案 2 :(得分:0)
不幸的是,MySQL不支持lag
来获取前一行的日期时间,但你可以使用变量来模拟它。
select max(timediff(datetime,prevDate)) from (
select *, @prevDate prevDate, @prevDate := datetime
from resets
order by datetime
) t1
或者如果要选择整行
select * from (
select *, @prevDate prevDate, @prevDate := datetime
from resets
order by datetime
) t1 order by timediff(datetime,prevDate) desc limit 1