生成可变时间步长
Generate variable time steps
大家好。
我正在尝试编写一个存储过程,以在几分钟内用时间簇填充维度 table。例如集群 = 30:00:00-00:29、00:30-00:59、01:00-01:29 等等。
到目前为止,我想不出更好的解决方案,只能按照提供的步骤循环超过 24 小时,当时间跳过 00:00 并重新开始时,存在无限循环的危险。
寻找可能的解决方案,我找到了一个优雅的解决方案:但没有弄清楚如何使其适应不同的时间步长。
*编辑:由于我正在处理 Azure Synapse SQL 池,因此无法使用序列生成和递归 CTE。
你可以使用递归cte
; with rcte as
(
select tm = cast('00:00' as time(0)) -- start time
union all
select tm = dateadd(minute, 30, tm) -- 30 mins increment
from rcte
where tm < '12:00' -- end time
)
select *
from rcte
计数table方法
declare @st time(0) = '00:00',
@en time(0) = '03:30';
with tally (n) as
(
-- 1000 rows
select row_number() over(order by (select null)) - 1
from (values (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
cross join (values (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
cross join (values (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
)
SELECT tm = dateadd(minute, n * 30, @st)
FROM tally
where n <= datediff(minute, @st, @en) / 30
感谢@Squirrel 在 Tally 表上指出作为循环的优雅且高效的替代品。我提出了以下解决方案:
declare @st time(0) = '00:00',
@en time(0) = '23:59',
@incr tinyint = 7; --variable increment in minutes
with tally (n) as
(
SELECT TOP 1439 --max amount of minutes from 00:00 to 23:59
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS [N]
FROM dbo.syscolumns tb1
CROSS JOIN dbo.syscolumns tb2
)
SELECT
dateadd(minute, (n -1 ) * @incr, @st) as StartTime
, CASE
WHEN dateadd(minute, (n - 1) * @incr, @st) < dateadd(minute, n * @incr, @st) THEN dateadd(minute, n * @incr, @st)
ELSE CONVERT(time(0), '23:59:59')
END AS EndTime --Preventing time to jump over 00:00 again
FROM tally
where n-1 <= datediff(minute, @st, @en) / @incr
试试这个:
DECLARE @TimeCluster TABLE
(
TimeBegin time
, TimeEnd time
)
;
DECLARE @TimeBegin time = '00:00'
, @TimeEnd time = '00:29'
, @TimeLapseMins int = 30
;
WHILE @TimeEnd <> '23:59'
BEGIN
INSERT INTO @TimeCluster VALUES (@TimeBegin, @TimeEnd)
SET @TimeBegin = DATEADD(MINUTE, @TimeLapseMins, @TimeBegin )
SET @TimeEnd = DATEADD(MINUTE, @TimeLapseMins, @TimeEnd )
;
END
;
SELECT * FROM @TimeCluster
大家好。
我正在尝试编写一个存储过程,以在几分钟内用时间簇填充维度 table。例如集群 = 30:00:00-00:29、00:30-00:59、01:00-01:29 等等。
到目前为止,我想不出更好的解决方案,只能按照提供的步骤循环超过 24 小时,当时间跳过 00:00 并重新开始时,存在无限循环的危险。
寻找可能的解决方案,我找到了一个优雅的解决方案:但没有弄清楚如何使其适应不同的时间步长。
*编辑:由于我正在处理 Azure Synapse SQL 池,因此无法使用序列生成和递归 CTE。
你可以使用递归cte
; with rcte as
(
select tm = cast('00:00' as time(0)) -- start time
union all
select tm = dateadd(minute, 30, tm) -- 30 mins increment
from rcte
where tm < '12:00' -- end time
)
select *
from rcte
计数table方法
declare @st time(0) = '00:00',
@en time(0) = '03:30';
with tally (n) as
(
-- 1000 rows
select row_number() over(order by (select null)) - 1
from (values (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
cross join (values (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
cross join (values (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
)
SELECT tm = dateadd(minute, n * 30, @st)
FROM tally
where n <= datediff(minute, @st, @en) / 30
感谢@Squirrel 在 Tally 表上指出作为循环的优雅且高效的替代品。我提出了以下解决方案:
declare @st time(0) = '00:00',
@en time(0) = '23:59',
@incr tinyint = 7; --variable increment in minutes
with tally (n) as
(
SELECT TOP 1439 --max amount of minutes from 00:00 to 23:59
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS [N]
FROM dbo.syscolumns tb1
CROSS JOIN dbo.syscolumns tb2
)
SELECT
dateadd(minute, (n -1 ) * @incr, @st) as StartTime
, CASE
WHEN dateadd(minute, (n - 1) * @incr, @st) < dateadd(minute, n * @incr, @st) THEN dateadd(minute, n * @incr, @st)
ELSE CONVERT(time(0), '23:59:59')
END AS EndTime --Preventing time to jump over 00:00 again
FROM tally
where n-1 <= datediff(minute, @st, @en) / @incr
试试这个:
DECLARE @TimeCluster TABLE
(
TimeBegin time
, TimeEnd time
)
;
DECLARE @TimeBegin time = '00:00'
, @TimeEnd time = '00:29'
, @TimeLapseMins int = 30
;
WHILE @TimeEnd <> '23:59'
BEGIN
INSERT INTO @TimeCluster VALUES (@TimeBegin, @TimeEnd)
SET @TimeBegin = DATEADD(MINUTE, @TimeLapseMins, @TimeBegin )
SET @TimeEnd = DATEADD(MINUTE, @TimeLapseMins, @TimeEnd )
;
END
;
SELECT * FROM @TimeCluster