【问题标题】:intersection of dates for an arbitrary number of time series in SQLSQL中任意数量时间序列的日期交集
【发布时间】:2016-06-01 19:12:50
【问题描述】:

如何在没有循环的情况下计算 SQL 中任意数量时间序列的日期交集?

鉴于我有一个包含 3 列的表格

  1. GroupId
  2. 开始日期
  3. 结束日期

对于每个 GroupId 有多个行 - 因此每个 GroupId 有多个开始/结束日期(在一个组内没有重叠)

我想做的是找到所有组之间的所有相交日期 所以如果第 1 组有以下日期

1/1/2001 - 1/31/2001
3/31/2001 - 4/5/2001

第 2 组有以下内容

1/25/2001 - 5/1/2001

第 3 组有以下内容

1/22/2001 - 4/1/2001

以上所有相交于:

1/25/2001 - 1/31/2001
3/31/2001 - 1/4/2001

如何在 SQL 中执行此操作?以下是一张表中 2 个日期范围的逻辑,但我需要一张表中的 n 个日期范围:

SELECT 
    case 
        when t1.StartDate > t2.StartDate then t1.StartDate 
        else t2.StartDate 
    END as StartDate,
    CASE WHEN t1.EndDate < t2.EndDate THEN t1.EndDate
        ELSE t2.EndDate
    END as EndDate
FROM Table1 t1
JOIN Table1 t2 ON t1.StartDate <= t2.EndDate AND t1.EndDate >= t2.StartDate    

(注意:作为附加约束,我在 linq to sql 中执行此操作)

提前致谢

【问题讨论】:

  • 提示:使用适当的软件(MySQL、Oracle、DB2 等)和版本标记数据库问题很有帮助,例如sql-server-2014。语法和功能的差异通常会影响答案。

标签: sql tsql sql-server-2012 time-series


【解决方案1】:

您可以通过分离各组中的日期并使用累积总和然后进行一些比较来做到这一点。在 SQL Server 2012+ 中,这看起来像:

with g as (
      select groupid, start as dte, 1 as enters, 0 as exits
      from t
      union all
      select groupid, dateadd(day, 1, end), 0, 1
      from t
     ),
     gs as (
      select groupid, dte, sum(enters) as enters, sum(exits) as exits,
             sum(sum(enters)) over (order by dte) as cumeenters,
             sum(sum(exits)) over (order by dte) as cumexits
      from g
      group by dte, groupid
     )
select ne, nextdte
from (select gs.*, lead(dte) over (order by dte) as nextdte
      from gs
     ) gs
where cumeenters - cumeexits = (select count(distinct groupid) from t);

处理如下:

  • 第一个子查询将开始日期和结束日期分隔为单独的记录。
  • 第二个累加起点和终点,得到累计值。
  • where 子句选择代表所有组的日期。

Here 是 SQL Fiddle。

【讨论】:

  • 有 3 个不同的 groupid。 groupid 1 有 2 行,groupid 2 和 2 各有 1 行,乘以 2(1 行作为开始,1 行作为结束)= 4 行,2 行和 2 行分别(in cte g')。只有 2 行的组如何累积达到 3? sqlfiddle.com/#!6/33f6a/5
  • 删除 partition by 对于 cumenters 和 cumexists 见:sqlfiddle.com/#!6/515cd/1
  • 哇 - 非常感谢 - 我需要几天时间才能将其转换为 linq
猜你喜欢
  • 2011-02-23
  • 2012-05-18
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多