【问题标题】:Count order of overlapping date ranges in SQL [closed]SQL中重叠日期范围的计数顺序[关闭]
【发布时间】:2015-01-09 09:20:07
【问题描述】:

我不确定标题是否描绘了正确的画面,但我会尝试解释一下。我有一张表,上面有开始和结束日期,以及团队成员 ID(有点像项目)。我需要确定它们何时重叠,计算重叠的数量,并确定重叠的顺序(按开始日期排序)。我的虚拟数据应该澄清,但我真正想要的是 3 个中的后者。这是我当前的表:

╔═════════════╦════════════╦════════════╗
║ Team Member ║ Start Date ║  End Date  ║
╠═════════════╬════════════╬════════════╣
║           1 ║ 01/01/2015 ║ 04/01/2015 ║
║           1 ║ 04/01/2015 ║ 06/01/2015 ║
║           1 ║ 06/01/2015 ║ 07/01/2015 ║
║           2 ║ 04/01/2015 ║ 06/01/2015 ║
║           2 ║ 06/01/2015 ║ 10/01/2015 ║
║           3 ║ 01/01/2015 ║ 09/01/2015 ║
║           3 ║ 11/01/2015 ║ 13/01/2015 ║
╚═════════════╩════════════╩════════════╝

这就是我想要的:

╔══════════════╦═════════════╦════════════╦════════════╗
║ OverlapOrder ║ Team Member ║ Start Date ║  End Date  ║
╠══════════════╬═════════════╬════════════╬════════════╣
║            0 ║           1 ║ 01/01/2015 ║ 04/01/2015 ║
║            1 ║           1 ║ 04/01/2015 ║ 06/01/2015 ║
║            0 ║           1 ║ 06/01/2015 ║ 07/01/2015 ║
║            0 ║           2 ║ 04/01/2015 ║ 06/01/2015 ║
║            1 ║           2 ║ 06/01/2015 ║ 10/01/2015 ║
║            0 ║           3 ║ 01/01/2015 ║ 09/01/2015 ║
║            0 ║           3 ║ 11/01/2015 ║ 13/01/2015 ║
╚══════════════╩═════════════╩════════════╩════════════╝

因此您可以看到团队成员不应该影响彼此的重叠顺序。

我目前正在使用 Access SQL,但不久将转移到 SQL Server,因此目标是解决方案!

附:您会看到第二个和第三个数据行具有相同的开始日期。这两个之间的重叠顺序是任意的;它们可以是任何一种方式。

编辑:更改了示例数据集,因此它涵盖了一个新的突出显示的可能性。 OverlapOrder 列可以从 0 到多高,具体取决于重叠项目的数量。

【问题讨论】:

  • 因此,overlapOrder 应该从 0 开始,并随着每个团队成员的每个重叠而递增?如果没有重叠,它会保持 0?还有一个列来排序吗?
  • 仅使用基于集合的 SQL 将变得极其困难。示例:如果您有 3 行 A、B、C,其中 A 与 B 重叠,B 与 C 重叠,但 A 不与 C 重叠,我从您的问题中得知您想要订购 0、1、2,但是要将所有这些行放到同一个组中,您将很难编写任何类型的 JOIN 子句或类似的将它们全部放入同一个组的子句。
  • 我想在这种情况下,A 和 C 将是 0,而 B 会是 1。我猜这将很难做到。按列排序将是团队成员、开始日期、结束日期

标签: sql sql-server date ms-access


【解决方案1】:

假设您能够迁移到 SQL Server 2005 或更高版本,您可以尝试以下使用 CTE 执行您想要的操作的解决方案:

;with cte as
(select *, row_number() over (partition by id order by startdate, enddate) rn
 from tbl)
select *, case when (datediff(dd,s.startdate,t.enddate) >= 0) then s.rn - 1 else 0 end
from cte s
left join cte t on s.id = t.id and t.rn = s.rn - 1

但是,您应该对此有所保留,因为此解决方案很可能是专门针对示例数据集设计的。我还没有用不同的案例进行测试。

Demo

【讨论】:

  • 赞成,因为它解决了原始解决方案。正如 Lasse V. Karlsen 指出的那样,如果 A 与 B 重叠,B 与 C 重叠,但 A 与 C 不重叠,则不起作用。这可能吗?谢谢
  • @marcus.d.johnson 在这种情况下,预期的结果是什么?我选择了 3 个范围 - 同月的 1 到 4、3 到 8 和 7 到 9,它给了我 0、1、2 的值。 rextester.com/NTBZN21686
  • 是的,在这种情况下,我想要 0,1,0
  • 我明白了。我同意其他评论者的观点 - 如果您将依赖关系视为更新示例中的内容,似乎没有任何简单的方法可以做到这一点。也许在应用层做起来可能更容易?
  • 嗯,是的,也许会。无论如何,谢谢,我会把你的标记为答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 2022-01-25
相关资源
最近更新 更多