sql - 查找开始/结束日期范围覆盖范围上限超过 20 天的 ID

标签 sql sql-server-2008 date

我需要查找第一个 StartDate 和最后一个 EndDate 之间超出日期范围 20 天或以上的所有 ID。

一个 ID 有多个开始日期和结束日期。在以下示例中,Id 1 有两个间隔,每个间隔都小于 20 天。应将其视为从 10/01/2012 到 10/30/2014 的一个范围,没有任何间隙。

1   10/01/2012  02/01/2013
1   01/01/2013  01/31/2013
1   02/10/2013  03/31/2013
1   04/15/2013  10/30/2014

ID 2 的结束日期 01/30/2013 和开始日期 05/01/2013 之间的间隔超过 20 天,因此必须由查询捕获。

2   01/01/2013  01/30/2013
2   05/01/2013  06/30/2014
2   07/01/2013  02/01/2014

Id 3 应被视为从 01/01/2012 到 06/01/2014 的一个范围,没有任何间隙。应忽略结束日期 02/28/2013 和开始日期 07/01/2013 之间的差距,因为从 01/01/2012 到 01/01/2014 的范围涵盖了该差距。

3   01/01/2012  01/01/2014
3   01/01/2013  02/28/2013
3   07/01/2013  06/01/2014

光标可以做到这一点,但它的工作速度非常慢并且 Not Acceptable 。

SQL fiddle :http://sqlfiddle.com/#!3/27e3f/2/0

最佳答案

使用你的 fiddle 模式,试试这个:

;WITH naivegaps AS
(
  SELECT ROW_NUMBER() OVER (ORDER BY id, startdate, MAX(dr1.enddate)) AS rn,
    dr1.Id, dr1.startdate, MAX(dr1.enddate) as enddate    
  FROM dateranges dr1
  GROUP BY dr1.Id, dr1.startdate
)
SELECT n1.id, n1.enddate as gap_start, n2.startdate AS gap_end, 
  datediff(dd, n1.enddate, n2.startdate) as gap_width, n3.*
FROM naivegaps n1
  CROSS APPLY
  (
    SELECT TOP 1 nx.id, nx.startdate
    FROM naivegaps nx
    WHERE n1.id = nx.id AND nx.rn > n1.rn
    ORDER BY nx.startdate
  ) n2
  OUTER APPLY
  (
    SELECT TOP 1 nx.id, nx.enddate
    FROM naivegaps nx
    WHERE n1.id = nx.id AND nx.rn < n1.rn
    ORDER BY nx.enddate DESC
  ) n3
WHERE datediff(dd, n1.enddate, n2.startdate) >= 20 AND (n3.enddate <= n1.enddate OR n3.enddate IS NULL)

顶部的 CTE 对以下检查的所有内容进行适当排序,并添加行号以方便排序检查。 CROSS APPLY 查找序列末尾与后续开头之间的所有间隙。 OUTER APPLY 检查完全包围相关间隙的范围(在 CROSS APPLY 中不会进行适当排序)

编辑:我将此解决方案的执行计划与 Joe Farrell 提供的递归 CTE 解决方案进行了比较。它们是明显不同的计划,但估计的效率非常接近(我的稍微好一点,大约 4%)。这可能会也可能不会转化为大型数据集的实际性能;我鼓励您测试这两种方法并使用最适合您的场景的方法。

关于sql - 查找开始/结束日期范围覆盖范围上限超过 20 天的 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24090227/

相关文章:

MySQL查询: UPDATE on duplicate key,追加数据

java - 如何在Java中将格式化日期(yyyy-MM-dd)转换为Unix时间?

sql - 从数据库中获取数据并填充分区列表

sql-server - 用文本更新 varchar 列的最快方法

SQL Server - INSERT 后返回值

mysql - 我无法将数据从主表复制到临时表

ios - Dateformatter 日期字符串返回 nil

sql-server - SQL Server 格式日期 DD.MM.YYYY HH :MM:SS

Mysql `AND` 运算符

php - 查询未在 PHP 中给出预期结果