我想做的是根据行中的日期范围获取15分钟的间隔并将其插入到另一个表中。
鉴于以下代码为我提供了目标范围内的日期范围:
DECLARE @Table1 TABLE (ID INT IDENTITY(0,1), TIMEVALUE DATETIME, TIMEVALUE2 DATETIME);
DECLARE @start DATETIME2(7) = '2018-01-04 10:55:00'
DECLARE @end DATETIME2(7) = '2018-01-05 03:55:00'
SELECT @start = dateadd(minute, datediff(minute,0,@start) / 15 * 15, 0);
WITH CTE_DT AS
(
SELECT @start AS DT
UNION ALL
SELECT DATEADD(MINUTE,15,DT) FROM CTE_DT
WHERE DT< @end
)
INSERT INTO @Table1
SELECT DT, DATEADD(minute,14,dt) FROM CTE_DT
OPTION (MAXRECURSION 0);
SELECT * FROM @Table1
结果:
ID TIMEVALUE TIMEVALUE2
0 2018-01-04 10:45:00.000 2018-01-04 10:59:00.000
1 2018-01-04 11:00:00.000 2018-01-04 11:14:00.000
2 2018-01-04 11:15:00.000 2018-01-04 11:29:00.000
3 2018-01-04 11:30:00.000 2018-01-04 11:44:00.000
4 2018-01-04 11:45:00.000 2018-01-04 11:59:00.000
5 2018-01-04 12:00:00.000 2018-01-04 12:14:00.000
6 2018-01-04 12:15:00.000 2018-01-04 12:29:00.000
7 2018-01-04 12:30:00.000 2018-01-04 12:44:00.000
8 2018-01-04 12:45:00.000 2018-01-04 12:59:00.000
..
..
我要完成的是从记录源中在i上方应用相同的逻辑。
所以,如果我的SourceData是
Col1 Col2 StartDate EndDate
AA AA 2018-01-01 13:25 2018-01-02 13:00
AA BB 2018-01-02 13:25 2018-01-03 13:00
因此,对于查询,无论如何都使用start和endate来仅通过查询来产生此结果
Col1 Col2 TIMEVALUE TIMEVALUE2
AA AA 2018-01-01 13:15:00 2018-01-01 13:29:00
AA AA 2018-01-01 13:30:00 2018-01-01 13:44:00
AA AA 2018-01-01 13:45:00 2018-01-01 13:59:00
...
...
AA AA 2018-01-02 12:30:00 2018-01-02 12:44:00
AA AA 2018-01-02 12:45:00 2018-01-02 12:59:00
AA AA 2018-01-02 13:00:00 2018-01-02 13:14:00
AA BB 2018-01-02 13:15:00 2018-01-02 13:29:00
AA BB 2018-01-02 13:30:00 2018-01-02 13:44:00
AA BB 2018-01-02 13:45:00 2018-01-02 13:59:00
...
...
AA BB 2018-01-03 12:30:00 2018-01-03 12:44:00
AA BB 2018-01-03 12:45:00 2018-01-03 12:59:00
AA BB 2018-01-03 13:00:00 2018-01-03 13:14:00
如果可以的话,我想避免使用游标。通过将必需的列与select语句一起传递,我设法使它与用户定义函数一起使用。我希望我能避免使用它。
答案 0 :(得分:0)
更改第一个查询的结尾,以代替
SELECT * FROM @Table1
它说:
SELECT * FROM @Table1 d
INNER JOIN SourceData sd
ON NOT(d.timevalue2 < sd.startdate OR d.timevalue1 > sd.enddate)
考虑采用第一个查询来生成日期,现在就运行直到2030年,然后将日期插入到实际表中。保持查询无处不在,以便可以在约11年内再次使用该查询,以便在日历表中添加更多行
答案 1 :(得分:0)
我将使用虚拟理货表格来生成日期,而不是使用rCTE(这是RBAR的一种形式)
--; is a statement terminator, not a "beginninator". It goes at the end, for the start.
WITH N AS(
SELECT NULL AS N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1 --10
CROSS JOIN N N2 --100
CROSS JOIN N N3 --1000
CROSS JOIN N N4 --10000
)
SELECT DATEADD(MINUTE,15*I,@Start)
FROM Tally
WHERE DATEADD(MINUTE,15*I,@Start) < @End;
如果要为一列组合生成15分钟的间隔,则可以再执行CROSS JOIN
。例如:
--Assume CTEs are already declared
SELECT V.Col1, V.Col2,
DATEADD(MINUTE,15*T.I,@Start)
FROM Tally T
CROSS JOIN (VALUES('AA','AA'),('AA','BB')) V(Col1, Col2) --This could be a CROSS APPLY to a DISTINCT, or similar is you wish
WHERE DATEADD(MINUTE,15*T.I,@Start) < @End;
答案 2 :(得分:0)
我不同意将结束时间设为14、29、44和59。它不会匹配诸如00:14:59.9999999
之类的值。话虽如此,这是您需要的加入条件:
SELECT *
FROM @Table1
INNER JOIN yourdata ON TIMEVALUE2 >= StartDate AND EndDate >= TIMEVALUE
将以上内容转换为专有结束日期(15、30、45和00)非常简单。只需将>=
更改为>
。