5

我有一个带有时间戳的表,我想将这个表划分为一个小时的间隔,从现在开始,然后倒退几个小时。我无法使用 T-SQL DATEDIFF函数获得所需的结果,因为它会计算分针在两个日期之间经过 12 次的次数 - 我想要分针在现在之间经过的次数时间戳和现在。

在 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 ...

结果:

    时间戳差异
    ********* ****
    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

我宁愿拥有的:

    -- 时间是现在,举例来说,13:40

    时间戳差异
    ********* ****
    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 或 3 -- 边缘情况,我真的不在乎哪个
    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 (或 0)
    11:40-12:40 2(或1)
    10:40-11:40 3(或2)
    09:40-10:40 4(或3)
4

3 回答 3

7

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

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

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

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

SELECT TimeStamp, (DATEDIFF(minute, TimeStamp, CURRENT_TIMESTAMP) /60) AS Diff FROM ...
于 2010-07-20T11:51:50.187 回答
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 多天的毫秒时间转换为有符号的 long:

SELECT DateAdd(Millisecond, 2147483647, 0) = '1900-01-25 20:31:23.647'
于 2010-07-21T00:58:20.200 回答
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
于 2010-07-21T02:41:16.517 回答