如何找到两个日期的时差?

时间:2019-06-20 19:32:56

标签: sql sql-server

我正在尝试使用DATEDIFF()函数来查找表中两个日期之间的差异。我遇到的问题是了解如何从表VS的开始日期中的最新日期中减去时间。

日期的格式为:YYYY-MM-DD HH:MM:SS

我已经尝试过了:

select FileName, '20:00' as StartTime, ModifiedDate, DATEDIFF(MINUTE, 
'20:00', ModifiedDate) as 'BackupTime' 
from BackLogData

但是它返回从开始时间开始的分钟数。

以下是表格的示例:

+-----------+-----------------------------+------------+
| StartTime |        ModifiedDate         | BackupTime |
+-----------+-----------------------------+------------+
| 20:00     | 2019-06-10 01:04:17.3692999 |   62817424 |
| 20:00     | 2019-06-10 00:53:23.4900986 |   62817413 |
| 20:00     | 2019-06-10 00:51:09.2363761 |   62817411 |
+-----------+-----------------------------+------------+

正确的表格:

+-----------+-----------------------------+------------+--+
| StartTime |        ModifiedDate         | BackupTime |  |
+-----------+-----------------------------+------------+--+
| 20:00     | 2019-06-10 01:04:17.3692999 |         11 |  |
| 20:00     | 2019-06-10 00:53:23.4900986 |          2 |  |
| 20:00     | 2019-06-10 00:51:09.2363761 |        291 |  |
+-----------+-----------------------------+------------+--+

4 个答案:

答案 0 :(得分:1)

您可以花费几分钟来计算差异,并使用dateaddcast将其转换为时间数据类型。请注意,如果您的差异大于24小时,则此方法将无效(时间数据类型最多存储24小时)。

SELECT FileName, '20:00' AS StartTime, ModifiedDate,
cast(dateadd(minute,DATEDIFF(MINUTE, RecordDate, ModifiedDate),'19000101') as time(0)) AS 'BackupTime' 
FROM BackLogData

示例:

SELECT 
cast(dateadd(minute,DATEDIFF(MINUTE, '2019-05-05 16:00:00', '2019-05-05 18:00:00'),'19000101') as time(0)) AS 'BackupTime' 

输出:

02:00:00

答案 1 :(得分:1)

如果您想要的只是从'20:00'小时开始的分钟数与ModifiedDate的时间之差,则只需比较时间值:

尝试:

✔ Builder initialized                                                                                                               
16:50:48
✔ Nuxt files generated                                                                                                              
16:50:48

✔ Client
  Compiled successfully in 22.22s


 ERROR  (node:9473) DeprecationWarning: Tapable.plugin is deprecated. Use new API on 
.hooks instead                                 16:50:56


Hash: 9ca2420933de76ba890d
Version: webpack 4.33.0
Time: 22216ms
Built at: 06/20/2019 4:51:18 PM

您获得一个奇怪的大价值是因为您试图从根本上找到1900-01-01 20:00与ModifiedDate之间的区别。

答案 2 :(得分:1)

Marc Guillot处在正确的轨道上,但我发现他的查询存在一些问题。这是一个修订:

--this is setup, you don't need this
CREATE TABLE t
    ([StartTime] time, [ModifiedDate] datetime)
;

INSERT INTO t
    ([StartTime], [ModifiedDate])
VALUES
    ('20:00', '2019-06-10 01:04:17'),
    ('20:00', '2019-06-10 00:53:23'),
    ('20:00', '2019-06-10 00:51:09')
;

--we now have a table with a TIME column (cast it in the cte if yours is not), a DATETIME
with LOGS as (
  select StartTime,
         ModifiedDate,
         DATEADD(DAY, -1, CAST(CAST(ModifiedDate as DATE) as DATETIME)) as ModifiedMidnightDayBefore,
         CAST(StartTime as DateTime) as StartDateTime,
         row_number() over (order by ModifiedDate) as num
  from t
)
select curr.StartTime, 
       curr.ModifiedDate, 
       datediff(minute, 
            COALESCE(
               prev.ModifiedDate, 
               curr.ModifiedMidnightDayBefore + curr.StartDateTime
            ),
            curr.ModifiedDate) as BackupTime
from 
  LOGS curr
  left join LOGS as prev on prev.num = curr.num - 1
order by curr.num

LOGS CTE在num = num-1上与其自身相连,从而将当前行和前一行数据放在一起。一行将没有以前的数据(空白),因此当我们进行datediff时,我们使用合并,就像ISNULL一样,但所有主要数据库供应商都支持。 COALESCE返回第一个非null参数。如果修改后的日期没有PREVious值,则用于填充值

prev vs current的DATEDIFF相当明显。如果没有以前的值,这就是逻辑上的窍门:

CTE还将修改后的日期日期时间转换为日期,以删除时间部分(将其设置为午夜)并返回日期时间(因此它从dateadd中出现为日期时间)。 Dateadd从中减去一天,因此它是前一天的午夜,然后我们将开始时间(晚上8点)添加到此。因此,有效地将表中的最小日期转换为午夜,然后推迟一天,然后添加晚上8点,因此它变为“修改日期前一天的晚上8点”,然后我们可以将日期精确地调整为291分钟

答案 3 :(得分:0)

要获取上一次时间,您可以将表自身连接起来。但是首先我要在CTE上对行进行编号,因此您现在可以设置一个简单的条件以将每一行与上一行连接起来。

此查询返回每个ModifiedTime与上一个ModifiedTime(或第一行的StartDate)之间的差,从而得出已发布的所需结果集:

declare @StartTime time = convert(time, '20:00');

declare @StartDate datetime = (select convert(datetime, dateadd(day, -1, convert(date, max(ModifiedDate)))) + 
                                      convert(datetime, @StartTime)
                               from BackLogData);

with LOGS as (
  select ModifiedDate,
         row_number() over (order by ModifiedDate) as num
  from BackLogData
)
select @StartTime as StartTime, 
       LOGS.ModifiedDate, 
       datediff(minute, 
                case when LOGS.num = 1 then @StartDate else PREVIOUS.ModifiedDate end,
                LOGS.ModifiedDate) as BackupTime
from LOGS
     left join LOGS as PREVIOUS on PREVIOUS.num = LOGS.num - 1
order by LOGS.num

PS:正如Caius Jard所指出的那样,为了能够直接计算ModifiedDate和StartTime之间的时间差,我们必须使用上一个ModifiedDate的日期部分减去一个(表示它从前一天开始)的日期部分将StartTime转换为日期时间。