对于每分钟,在范围之间添加行

时间:2017-11-21 15:22:51

标签: sql tsql datetime date-range

我有日期范围的表格

enter image description here

我需要在这个范围之间添加行。我必须把这张桌子弄成几分钟。我怎样才能添加这些额外的行

2 个答案:

答案 0 :(得分:1)

来自@MatthewBaker的递归CTE选项只需要进行细微更改即可满足您的需求。

WITH
   by_minute
AS
(
    SELECT *, datetime_from, minute_marker FROM your_table
    UNION ALL
    SELECT *, DATEADD(minute, 1, minute_marker) FROM by_minute WHERE DATEADD(minute, 1, minute_marker) < datetime_to
)

SELECT
    *
FROM
    by_minute
OPTION
    (MAXRECURSION 0)

OPTION (MAXRECURSION 0)允许SQL Server以递归方式生成超出默认值100的分钟。但是,如果生成的间隔超过几百分钟,我不建议这样做。到一天[1440分钟])

在这种情况下,更简单的方法是利用数字表,然后简单地加入。

创建此类表格的示例可以是:https://www.mssqltips.com/sqlservertip/4176/the-sql-server-numbers-table-explained--part-1/

从那里,您只需加入您需要的行数......

SELECT
    yourTable.*,
    DATEADD(minute, Numbers.[Number], yourTable.datetime_from)  AS minute_marker
FROM
    yourTable
INNER JOIN
     dbo.Numbers
         ON  Numbers.[Number] >= 0
         AND Numbers.[Number] <  DATEDIFF(minute, yourTable.datetime_from, yourTable.datetime_to)

我的另一个建议是不要用第59秒代表一分钟结束。如果您在59.600秒获得数据怎么办?那是在分钟结束之后,但在新的开始之前?而是使用包含开始和排他结束的标记...

The first minute of 2012 = '2012-01-01 00:00:00.000' -> '2012-01-01 00:01:00.000'
The final minute of 2012 = '2012-12-31 23:59:00.000' -> '2013-01-01 00:00:00.000'

使用这样的结构,您只需要my_point_in_time >= start AND my_point_in_time < end,并且您永远不必担心所使用的数据类型的精度。

(它也符合人类的自然语言。当我们说between 1 and 2之类的内容时,我们通常指的是>= 1 AND < 2。)

答案 1 :(得分:0)

如果您使用以下内容:

WITH    cte
      AS (SELECT    CAST('2017-01-01 00:00:00' AS DATETIME) AS startTime
          UNION ALL
          SELECT    DATEADD(MINUTE, 1, startTime)
          FROM      cte
          WHERE     startTime < '2017-01-02 00:00:00'
         )
SELECT  *
FROM    cte

选项(MAXRECURSION 0)

它会给你一分钟的结果。替换你想要的范围。然后,您可以将其用作编写插入的基础。迭代CTE不是最有效的,但可能是最简单的