sql - 如何从重叠日期中获取单独的时间间隔

标签 sql sql-server tsql date overlap

我有一个包含开始和结束日期的表格,如下所示

drop table if exists #Temp
select * 
into #Temp
from (values (1, 1, '2011-10-09', '2011-10-20'),
             (2, 1, '2011-10-14', '2011-10-30'),
             (3, 1, '2012-05-21', '2012-05-25')
     ) as value (id, userId, d1, d2)

这给了我这个初始表:

id  userId    d1            d2
1   1         2011-10-09    2011-10-20
2   1         2011-10-14    2011-10-30
3   1         2012-05-21    2012-05-25

问题:我想要实现的是从这 2 个重叠日期中获取 3 个间隔。如何实现?

select * 
from 
    #Temp t1
    join #Temp t2
        on t1.userId = t2.userId
        and t1.id != t2.id
where
    t1.d1 <= t2.d2
    and t1.d2 >= t2.d1
order by t1.d1

给我

id  userId    d1            d2              id  userId    d1            d2
1   1         2011-10-09    2011-10-20      2   1         2011-10-14    2011-10-30
2   1         2011-10-14    2011-10-30      1   1         2011-10-09    2011-10-20  

我不确定如何从这里继续。

我想要实现的是下表,其中重叠被分开。

预期结果:

userId  d1          d2              
1       2011-10-09  2011-10-14
1       2011-10-14  2011-10-20
1       2011-10-20  2011-10-30
1       2012-05-21  2012-05-25

最佳答案

一种方法是对数据进行逆透视,然后对日期进行排序,然后再次对数据进行透视,排除一些记录。

WITH dataSource AS
(
    select id, userId, d1
    from #Temp t1
    UNION ALL
    select id, userId, d2
    from #Temp t1
), DataSourceOrdered AS
(
    SELECT 
        id, userId, d1,
        row_number () OVER (PARTITION BY userId ORDER By d1) as rowid
    FROM dataSource DS1
)
SELECT *
FROM DataSourceOrdered ds1
INNER JOIN DataSourceOrdered ds2
    ON ds1.userId = ds2.[userId]
    and ds1.[rowid] + 1 = ds2.[rowid]
    and exists (
        SELECT 1 
        FROM #Temp x 
        WHERE ds1.[d1] >= x.d1 and ds1.[d1] < x.d2 and ds1.userId = x.userId
    )

它可能需要根据您的真实数据进行一些更改,但对于当前的数据,它似乎可以工作。

enter image description here

关于sql - 如何从重叠日期中获取单独的时间间隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53666653/

相关文章:

sql-server - 如果 SQL Server 2008 r2 中存在,则删除列

sql-server - 如何对T-SQL声明的表变量的两列进行设置和索引?

sql-server - SQL Proc 'Conversion failed' 从 varchar 到 int。为什么转换?

sql - PostgreSQL:更新主键,避免冲突

sql - 在计算查询中的行数时,我应该使用 count(*) 还是 count(a, b, c.., z)?

sql-server - 为什么在通过 sp_executeSQL 过程执行时,完全相同的 SQL 查询会产生不同的执行计划?

sql - 确定此 Delete 语句的作用

SQL Server : Arithmetic overflow error converting expression to data type int

c++ - 验证数据库的结构? (C++/Qt 中的 SQLite)

SQL Server 性能和索引 View