Rus*_*hta 5 sql-server datetime interval sql-server-2019
我经常遇到以下问题。我有两张间隔表。它们受日期限制(没有时间部分)。每个表中的间隔不重叠。
开始时间 | 结束时间 |
---|---|
2015-01-03 | 2015-03-02 |
2015-03-05 | 2015-04-01 |
开始时间 | 结束时间 |
---|---|
2015-01-07 | 2015-02-27 |
2015-03-01 | 2015-03-13 |
2016-01-01 | 2016-01-02 |
我想找到两个表的集合差异,即代表第一个表中而不是第二个表中的时间的间隔。
上面的虚拟示例所需的输出:
开始时间 | 结束时间 |
---|---|
2015-01-03 | 2015-01-06 |
2015-02-28 | 2015-02-28 |
2015-03-14 | 2015-04-01 |
即,如果第一个表的日期在下面用黄色标记,并且第二个表的范围用框包围,我将寻找未装箱的黄色日期的连续范围。
我目前将两端都视为包含间隔,并使用 DateTime 作为时间戳。我当前的方法是通过三重自连接(恶心)获取第二个表的补集,然后通过连接将结果与第一个表相交。不好玩。
有更好的方法吗?
考虑到各种简化假设(只有日期并且表格内没有重叠的间隔),我可能会介意让事情变得简单。
首先创建一个辅助数字表(从零开始)
CREATE TABLE dbo.SmallNumbers
(
Number SMALLINT PRIMARY KEY
)
INSERT INTO dbo.SmallNumbers
SELECT TOP 32768 ROW_NUMBER() OVER (ORDER BY @@SPID)-1 AS Number
FROM sys.all_columns c1, sys.all_columns c2
Run Code Online (Sandbox Code Playgroud)
然后,下面的代码将范围扩展到其组成日期,用于EXCEPT
查找差异以及间隙和岛屿技术来将范围缩小。由于每个日期只会出现一次,我们可能只会谈论扩展到每十年覆盖的几千个日期。
WITH UnmatchedDates(Date) AS
(
SELECT DATEADD(DAY,N.Number, StartTs)
FROM Table1
JOIN dbo.SmallNumbers N ON N.Number <= DATEDIFF(DAY, StartTs, EndTs)
EXCEPT
SELECT DATEADD(DAY,N.Number, StartTs)
FROM Table2
JOIN dbo.SmallNumbers N ON N.Number <= DATEDIFF(DAY, StartTs, EndTs)
),
UnmatchedDatesWithGrp(Date, Grp) AS
(
SELECT Date,
DATEDIFF(DAY, 0, Date) - ROW_NUMBER() OVER (ORDER BY Date)
FROM UnmatchedDates
)
SELECT StartTs = MIN(Date),
EndTs = MAX(Date)
FROM UnmatchedDatesWithGrp
GROUP BY Grp
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
357 次 |
最近记录: |