【问题标题】:SQL DateDiff in Minutes Spanning Over NightSQL DateDiff 以分钟为单位跨越一夜
【发布时间】:2019-05-08 14:04:12
【问题描述】:

试图获取日期时间字段和时间字段之间的分钟差。我正在使用 datediff 函数。

当开始时间从一个日期开始,如“2018-01-08 22:35:55.043”,结束时间为第二天,如“00:35:56.2136644”,结果从结束时间开始计数到开始时间。

例子:

select DATEDIFF(MINUTE, CAST('2018-01-08 22:35:55.043' AS TIME), '00:35:56.2136644') AS minDiff1
select DATEDIFF(MINUTE,  '00:35:56.2136644', CAST('2018-01-08 22:35:55.043' AS TIME)) AS minDiff2
select DATEDIFF(MINUTE, CONVERT(TIME, '2018-01-08 22:35:55.043'), '00:35:56.2136644') AS minDiff3
select DATEDIFF(MINUTE, '00:35:56.2136644', CONVERT(TIME, '2018-01-08 22:35:55.043')) AS minDiff4

结果与我的预期不同。期望的结果是 120 分钟。

minDiff1 = -1320

minDiff2 = 1320

minDiff3 = -1320

minDiff4 = 1320

原始查询

select DATEDIFF(MINUTE, CAST(test_start_datetime as TIME), test_end_time) AS minDiff
from user_exam  

【问题讨论】:

  • 将您的时间字段转换为日期字段 - 这是使其可靠的唯一方法。
  • 这是模棱两可的。它在哪里说 00:35:56.2136644 是 2018-01-09 00:35:56.2136644 而不是 2018-01-10 00:35:56.2136644 或 2099-01-09 00:35:56.2136644。存储完整日期。
  • 你怎么知道一个时间是在 any 给定的一天,例如从 23:00 到 23:10 可能是 13 天零十分钟?是否有一些可以应用的限制,例如间隔从不超过 8 小时,因此 09:00 到 08:00 无效,因为它会(至少)23 小时?
  • 如果您意识到它是按天计算的,您显然需要将天与时间包括在内,即日期时间。因此,为函数提供 2 个日期时间,而不是坚持时间或将日期时间转换为时间。

标签: sql sql-server tsql datetime time


【解决方案1】:

以下假设时间属于同一天或次日:

SELECT *, CASE
    -- same day -- start time is less than end time
    WHEN CAST(datetimecol AS time) <= timecol THEN DATEDIFF(MINUTE, CAST(datetimecol AS time), timecol)
    -- next day -- start time is more than end time (it rolled over into next day)
    ELSE 1440 - DATEDIFF(MINUTE, timecol, CAST(datetimecol AS time))
END
FROM (VALUES
    (CAST('2018-01-08 22:35:55.043' AS DATETIME), CAST('22:35:55.0433333' AS TIME)),
    (CAST('2018-01-08 22:35:55.043' AS DATETIME), CAST('23:35:56.2136644' AS TIME)),
    (CAST('2018-01-08 22:35:55.043' AS DATETIME), CAST('00:35:56.2136644' AS TIME))
) AS tests(datetimecol, timecol)

在上面的例子中,1440 是 24 小时的分钟数。

Demo on DB Fiddle

【讨论】:

    【解决方案2】:

    如果您想查看 120,那么平均时差不足以满足您的目的。有了您的问题,您想找出 22:35 和第二天 00:35 之间的区别 您需要找到类似这样的 DATETIME 差异:

    SELECT DATEDIFF(MINUTE,         CAST(GETDATE() AS DATETIME)
                                   +CAST(CAST('22:35:55.2136644' AS TIME) AS DATETIME)
                                 , 
                                    CAST(GETDATE() AS DATETIME)+1
                                   +CAST(CAST('00:35:56.2136644' AS TIME)AS DATETIME)
    
                    ) AS minDiff1
    

    【讨论】:

    • 感谢您的帮助泽基
    【解决方案3】:

    让我们首先重新考虑您的示例:

    select DATEDIFF(MINUTE, CAST('2018-01-08 22:35:55.043' AS TIME), '00:35:56.2136644') AS minDiff1
    select DATEDIFF(MINUTE,  '00:35:56.2136644', CAST('2018-01-08 22:35:55.043' AS TIME)) AS minDiff2
    select DATEDIFF(MINUTE, CONVERT(TIME, '2018-01-08 22:35:55.043'), '00:35:56.2136644') AS minDiff3
    select DATEDIFF(MINUTE, '00:35:56.2136644', CONVERT(TIME, '2018-01-08 22:35:55.043')) AS minDiff4
    

    从日期时间转换/转换到时间会丢弃日期部分。因此,您实际上正在运行:

    select DATEDIFF(MINUTE, '22:35:55.043'', '00:35:56.2136644') AS minDiff1
    select DATEDIFF(MINUTE,  '00:35:56.2136644', '22:35:55.043') AS minDiff2
    select DATEDIFF(MINUTE, '22:35:55.043', '00:35:56.2136644') AS minDiff3
    select DATEDIFF(MINUTE, '00:35:56.2136644'22:35:55.043') AS minDiff4
    

    此时,您似乎没有考虑 DATEDIFF 是定向的这一事实,这意味着它从第二个参数到第三个参数计数(传递的第一个参数单元)。因此,由于 00:35 比 22:35(同一天)早 1320 分钟,因此 00:35 -> 22:35 返回 1320,而 22:35 -> 00:35 返回 -1320。


    确切地说,由于DATEDIFF 使用日期时间,您的时间/时间表示字符串会隐式转换为日期。由于您没有提供日期,因此使用的日期是值为 0 的日期:1900 年 1 月 1 日。这是函数作用的常见日期。

    【讨论】:

    • 感谢您的帮助 - “您似乎没有考虑 DATEDIFF 是定向的事实”我看到了这种模式,但无法弄清楚如何摆脱字面计数。
    猜你喜欢
    • 2014-04-05
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 2020-06-06
    相关资源
    最近更新 更多