T-SQL DateDiff - 按“完整小时前”分区,而不是“从00开始的分钟数”

时间:2010-07-20 11:45:28

标签: sql-server tsql datetime datediff

我有一张带有时间戳的表格,我希望将此表格划分为长达一小时的时间间隔,从现在开始并向后退几个小时。我无法通过T-SQL DATEDIFF函数得到我需要的结果,因为它计算了分针在两个日期之间经过12的次数 - 我想要它们分针传递的次数< em>现在在时间戳和现在之间的。

在T-SQL中有直接的方法吗?

更新 在回复评论时,这里有一些示例数据,我正在使用的查询以及我得到的结果,以及我想要的结果。

示例数据:

TimeStamp
*********
2010-07-20 11:00:00.000
2010-07-20 10:44:00.000
2010-07-20 10:14:00.000
2010-07-20 11:00:00.000
2010-07-20 11:40:00.000
2010-07-20 10:16:00.000
2010-07-20 13:00:00.000
2010-07-20 12:58:00.000

当前查询:

SELECT TimeStamp, DATEDIFF(HOUR, TimeStamp, CURRENT_TIMESTAMP) AS Diff FROM ...

结果:

    TimeStamp                   Diff
    *********                   ****
    2010-07-20 11:00:00.000     2
    2010-07-20 10:44:00.000     3
    2010-07-20 10:14:00.000     3
    2010-07-20 11:00:00.000     2
    2010-07-20 11:40:00.000     2
    2010-07-20 10:16:00.000     3
    2010-07-20 13:00:00.000     0
    2010-07-20 12:58:00.000     1

我宁愿拥有:

    -- The time is now, for the sake of the example, 13:40

    TimeStamp                   Diff
    *********                   ****
    2010-07-20 11:00:00.000     3 -- +1
    2010-07-20 10:44:00.000     3
    2010-07-20 10:14:00.000     4 -- +1
    2010-07-20 11:00:00.000     3 -- +1
    2010-07-20 11:40:00.000     2 or 3 -- edge case, I don't really care which
    2010-07-20 10:16:00.000     4 -- +1
    2010-07-20 13:00:00.000     1 -- +1
    2010-07-20 12:58:00.000     1

我已使用+1标记了更改的结果。另外,我真的不在乎这是0索引还是1索引,但基本上,如果它现在是13:40我想要时间跨度得到相同的值

    12:40-13:40    1 (or 0)
    11:40-12:40    2 (or 1)
    10:40-11:40    3 (or 2)
    09:40-10:40    4 (or 3)

3 个答案:

答案 0 :(得分:7)

你能不能只使用DATEDIFF(minute,..然后将结果除以60并取整数值。 e.g。

 SELECT DATEDIFF(minute, '2010-07-20 06:00', GETDATE())/60

我相信这将被隐式地转换为int,因为datediff返回一个int,它给出整数小时没有舍入。

使用您更新的帖子中的确切查询:

SELECT TimeStamp, (DATEDIFF(minute, TimeStamp, CURRENT_TIMESTAMP) /60) AS Diff FROM ...

答案 1 :(得分:0)

您可以对此进行分组:

SELECT DateDiff(Hour, 0, GetDate() - TimeStamp)

如果您想知道它代表的时间,请将其计算回来:

DateAdd(Hour, -DateDiff(Hour, 0, GetDate() - TimeStamp), GetDate())

如果你不喜欢减去日期,那么它仍然可以完成,但变得有点困难。而不只是在黑暗中拍摄我编写了一个查询来证明这是正确的。

SELECT
   TimeStamp,
   Now = GetDate(),
   HourDiff = DateDiff(Hour, 0, GetDate() - TimeStamp),
   HourCalc = DateAdd(Hour, -DateDiff(Hour, 0, GetDate() - TimeStamp), GetDate()),
   HourDiff2 = DateDiff(Hour, DateAdd(Millisecond, AdjustMs, TimeStamp), DateAdd(Millisecond, AdjustMs, GetDate())),
   HourCalc2 = DateAdd(Hour, -DateDiff(Hour, DateAdd(Millisecond, AdjustMs, TimeStamp), DateAdd(Millisecond, AdjustMs, GetDate())), GetDate())
FROM
   (
      SELECT DateAdd(Second, -3559, GetDate())
      UNION ALL SELECT DateAdd(Second, -3600, GetDate())
      UNION ALL SELECT DateAdd(Second, -3601, GetDate())
   ) x (TimeStamp)
   CROSS JOIN (
      SELECT 3599997 - DateDiff(Millisecond, 0, DateAdd(Hour, -DateDiff(Hour, 0, GetDate()), GetDate()))
   ) D (AdjustMs)

不幸的是,我不得不利用我对datetime数据类型的分辨率(1/300秒)的了解,因此3600000 - 3 = 3599997.如果根据TimeStamp而不是GetDate()计算毫秒调整,那么这就不行了不需要,但由于派生表D中的大表达式必须在主查询中使用两次,取代了AdjustMs,因此会更加混乱。

计算比看起来更复杂,因为你不能只计算随机日期之间的毫秒差异,否则你会得到一个溢出错误。如果您知道可能的日期范围,您可以使用与“19000101 00:00:00.000”(上述表达式中的0)不同的锚定日期进行直接毫秒计算。

第二个想法,你只需要24天以上的毫秒进入签名的长篇:

SELECT DateAdd(Millisecond, 2147483647, 0) = '1900-01-25 20:31:23.647'

答案 2 :(得分:0)

我用

FLOOR(24 * CAST(CURRENT_TIMESTAMP-[TimeStamp] as float))

测试用例

DECLARE @GetDate datetime
set @GetDate = '2010-07-20 13:40:00.000';

WITH TestData As
(
select CAST('2010-07-20 11:00:00.000' AS DATETIME) AS [TimeStamp]  UNION ALL
select '2010-07-20 10:44:00.000'  UNION ALL    
select '2010-07-20 10:14:00.000'  UNION ALL   
select '2010-07-20 11:00:00.000'  UNION ALL   
select '2010-07-20 11:40:00.000'  UNION ALL   
select '2010-07-20 10:16:00.000'  UNION ALL   
select '2010-07-20 13:00:00.000'  UNION ALL  
select '2010-07-20 12:58:00.000'
)

SELECT [TimeStamp], FLOOR(24 * CAST(@GetDate-[TimeStamp] as float))  AS Diff
FROM TestData

<强>结果

(您需要添加1才能获得您发布的确切结果,但您说您并不关心0或1索引)

TimeStamp               Diff
----------------------- ----------------------
2010-07-20 11:00:00.000 2
2010-07-20 10:44:00.000 2
2010-07-20 10:14:00.000 3
2010-07-20 11:00:00.000 2
2010-07-20 11:40:00.000 2
2010-07-20 10:16:00.000 3
2010-07-20 13:00:00.000 0
2010-07-20 12:58:00.000 0