【问题标题】:Get the ten minute intervals from a range of datetimes从一系列日期时间中获取十分钟的间隔
【发布时间】:2012-06-25 16:41:15
【问题描述】:

我有一个包含日期时间值范围的日期时间列。我想用所有这些日期时间值创建另一列,但要向下舍入到十分钟。

所以,是这样的:

datetimesent              |     ten_minute_column

2012-06-11 18:27:58.000   |     2012-06-11 18:20:00.000
2012-06-15 15:19:08.000   |     2012-06-15 15:10:00.000
...                       |

我玩得最远的就是把它放在分钟的桶槽中。 我是这样做的:

SELECT DatetimeSent,
    DATEADD(Minute, DATEDIFF(Minute, 0, DatetimeSent), 0) AS Minute_bucket
FROM allrequests

但我需要十分钟的桶槽。

【问题讨论】:

标签: sql sql-server sql-server-2008


【解决方案1】:

试试这个:

select dateadd(minute, datepart(minute, datetimesent) / 10 * 10, 
dateadd(hour, datediff(hour, 0,datetimesent), 0)) ten_minute_column
from 
(select cast('2012-06-11 18:27:58.000' as datetime) datetimesent
union all
 select cast('2012-06-15 15:19:08.000' as datetime)) a

【讨论】:

    【解决方案2】:

    您可以使用许多功能来做到这一点:

    WITH D AS
    (   SELECT  CURRENT_TIMESTAMP [DateField]
        UNION ALL
        SELECT  DATEADD(MINUTE, 5, CURRENT_TIMESTAMP)
    )
    SELECT  DATEADD(MINUTE, (10 * FLOOR(DATEPART(MINUTE, DateField) / 10.0)) - DATEPART(MINUTE, DateField), DATEADD(MINUTE, DATEDIFF(MINUTE, 0, DateField), 0)) AS RoundedDate
    FROM    D
    

    这里的要点是去掉超过 10 分钟间隔的分钟数,然后从实际分钟数中减去(除去秒数)。

    这可以通过将一些函数移动到一个连接来稍微整理一下。但是,我认为这不会带来任何性能提升(根本没有进行任何测试)

    ;WITH T AS
    (   SELECT  Number,
                (10 * FLOOR(Number / 10.0)) - Number [RoundedDifference]
        FROM    (   SELECT  ROW_NUMBER() OVER(ORDER BY Object_ID) - 1 [Number]
                    FROM    sys.All_Objects
                ) n
        WHERE   Number < 60
    ), D AS
    (   SELECT  CURRENT_TIMESTAMP [DateField]
        UNION ALL
        SELECT  DATEADD(MINUTE, 5, CURRENT_TIMESTAMP)
    )
    SELECT  DateField,
            DATEADD(MINUTE, RoundedDifference, DATEADD(MINUTE, DATEDIFF(MINUTE, 0, DateField), 0)) [RoundedDate]
    FROM    D
            INNER JOIN T
                ON DATEPART(MINUTE, DateField) = Number
    

    【讨论】:

    • 它看起来不像公认的答案那么干净,但这绝对是这个问题的正确答案!
    【解决方案3】:
    SELECT  DatetimeSent,
            Dateadd(ms, -Datepart(ms, Dateadd(minute, Datediff(minute, 0, 
                                                        Dateadd(minute, 
                                                        -Datepart(minute, 
                                                         datetimesent) 
                                                        %10, 
                                                        datetimesent)), 0 
                                                    ) 
                    ), Dateadd(minute, Datediff(minute, 0, Dateadd(minute, 
                                                           - 
                                       Datepart( 
                                       minute, 
                                                       datetimesent 
                                       )% 
                                       10, 
                                         datetimesent 
                                                       )), 0)) AS Minute_bucket
    FROM   allrequests 
    

    【讨论】:

      【解决方案4】:

      假设从不存在毫秒,您可以通过这种方式去除分钟和秒,然后对结果进行分组:

      SELECT DATEADD(SECOND, -(CONVERT(INT, RIGHT(CONVERT(CHAR(2),
        DATEPART(MINUTE, GETDATE())),1))*60)-(DATEPART(SECOND,GETDATE())), GETDATE());
      

      这是一个查询,它根据表(或表的子集)的最小和最大日期获取正确的时隙数:

      DECLARE @x TABLE(datetimesent DATETIME);
      INSERT @x SELECT '2012-06-11 18:27:58.000'
      UNION ALL SELECT '2012-06-15 15:19:08.000';
      
      DECLARE @start SMALLDATETIME, @end SMALLDATETIME, @i INT;
      
      SELECT @start = CONVERT(DATE, MIN(datetimesent)), @end = CONVERT(DATE,
      MAX(datetimesent))
      FROM @x
      -- WHERE ...;
      
      SELECT @i = DATEDIFF(DAY, @start, @end) * 144;
      
      ;WITH slots(ten_minute_column) AS
      (
         SELECT TOP (@i * 144) DATEADD(MINUTE, 10 * (ROW_NUMBER() OVER
         (ORDER BY s1.[object_id])-1), @start)
         FROM sys.all_columns AS s1
         -- you may need to cross join to another table if this doesn't
         -- provide enough rows. Depends on overall datediff...
      )
      SELECT x.datetimesent, slots.ten_minute_column
       FROM @x AS x
       INNER JOIN slots
       ON x.datetimesent >= slots.ten_minute_column
       AND x.datetimesent < DATEADD(MINUTE, 10, slots.ten_minute_column)
       -- WHERE ...;
      

      结果:

      datetimesent              ten_minute_column
      -----------------------   -------------------
      2012-06-11 18:27:58.000   2012-06-11 18:20:00
      2012-06-15 15:19:08.000   2012-06-15 15:10:00
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-15
        • 2019-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多