gpt4 book ai didi

sql - SQL Server 中的重叠时间

转载 作者:行者123 更新时间:2023-12-02 05:39:25 25 4
gpt4 key购买 nike

我有一张这样的 table

ColumnId Intime                   Outtime
1 01/02/2009 10.00.000 01/02/2009 20.00.0000
2 01/02/2009 2.00.000 01/02/2009 2.00.0000
3 01/02/2009 2.00.000 01/02/2009 5.00.0000
4 01/02/2009 3.3.0.000 01/02/2009 5.00.0000
5 01/02/2009 10.00.000 01/02/2009 22.00.0000
6 01/02/2009 3.00.000 01/02/2009 4.00.0000

我有这样的列和值。我喜欢查找重叠记录以及特定日期有多少重叠记录。一天中 1-24 的时间重叠。

注意:- 我的表有数百万条记录。

例如,在第一个值中登录 10 并在 20 时注销。在 5 中记录在 10 时登录并在 22 时注销,因此 5th 与 first 重叠。表中没有可用的索引。

请给我查询的答案。

我需要在 SQL Server 2005 中执行查询

最佳答案

在我的脑海中,假设两列都有索引,你可以使用这样的东西:

SELECT a.ColumnId
,a.InTime
,a.OutTime
,b.ColumnId AS OverlappingId
,b.InTime AS OverlappingInTime
,b.OutTime AS OverlappingOutTime
FROM TimeTable AS a
JOIN TimeTable AS b ON ((a.InTime BETWEEN b.InTime AND b.OutTime)
OR (a.OutTime BETWEEN b.InTime AND b.OutTime)
OR (a.InTime < b.InTime AND a.OutIme > b.OutTime))
AND (a.ColumnId != b.ColumnId)

但我真的不确定这个查询在您提到的包含数百万条记录的表中的性能。

编辑添加,并再次编辑:

Vadim K.的评论之后,我注意到我之前写的查询缺少一个完全重叠的情况,即一个范围完全覆盖另一个范围。上面是我修改后的查询,下面是原来的查询:

SELECT a.ColumnId 
,a.InTime
,a.OutTime
,b.ColumnId AS OverlappingId
,b.InTime AS OverlappingInTime
,b.OutTime AS OverlappingOutTime
FROM TimeTable AS a
JOIN TimeTable AS b ON ((a.InTime BETWEEN b.InTime AND b.OutTime)
OR (a.OutTime BETWEEN b.InTime AND b.OutTime))
AND (a.ColumnId != b.ColumnId)

使用问题初始数据进行测试:

+--------+------------------+------------------+
|ColumnId| InTime | OutTime |
+--------+------------------+------------------+
| 1 | 01/02/2009 10:00 | 01/02/2009 20:00 |
| 2 | 01/02/2009 2:00 | 01/02/2009 2:00 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 |
| 4 | 01/02/2009 3:03 | 01/02/2009 5:00 |
| 5 | 01/02/2009 10:00 | 01/02/2009 22:00 |
| 6 | 01/02/2009 3:00 | 01/02/2009 4:00 |
+--------+------------------+------------------+

运行原始查询,我们得到以下结果:

+--------+------------------+------------------+-------------+
|ColumnId| InTime | OutTime |OverlappingId|
+--------+------------------+------------------+-------------+
| 1 | 01/02/2009 10:00 | 01/02/2009 20:00 | 5 |
| 2 | 01/02/2009 2:00 | 01/02/2009 2:00 | 3 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 | 2 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 | 4 |
| 4 | 01/02/2009 3:03 | 01/02/2009 5:00 | 3 |
| 4 | 01/02/2009 3:03 | 01/02/2009 5:00 | 6 |
| 5 | 01/02/2009 10:00 | 01/02/2009 22:00 | 1 |
| 6 | 01/02/2009 3:00 | 01/02/2009 4:00 | 3 |
| 6 | 01/02/2009 3:00 | 01/02/2009 4:00 | 4 |
+--------+------------------+------------------+-------------+

运行更新后的查询,我们得到以下结果:

+--------+------------------+------------------+-------------+
|ColumnId| InTime | OutTime |OverlappingId|
+--------+------------------+------------------+-------------+
| 1 | 01/02/2009 10:00 | 01/02/2009 20:00 | 5 |
| 2 | 01/02/2009 2:00 | 01/02/2009 2:00 | 3 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 | 2 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 | 4 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 | 6 | << missing row
| 4 | 01/02/2009 3:03 | 01/02/2009 5:00 | 3 |
| 4 | 01/02/2009 3:03 | 01/02/2009 5:00 | 6 |
| 5 | 01/02/2009 10:00 | 01/02/2009 22:00 | 1 |
| 6 | 01/02/2009 3:00 | 01/02/2009 4:00 | 3 |
| 6 | 01/02/2009 3:00 | 01/02/2009 4:00 | 4 |
+--------+------------------+------------------+-------------+

是的,有些 ID 是重复的,但那是因为它们与不同的记录重叠。

该问题还询问重叠行数。我不确定,而且问题还不够清楚,如果它想要关于原始表的重叠行数。

有些人建议使用 a.ColumnId < b.ColumnIda.ColumnId > b.ColumnId然而,为了避免重复,它仍然不起作用,因为如果我们进行第一次比较,我们将得到以下结果:

+--------+------------------+------------------+-------------+
|ColumnId| InTime | OutTime |OverlappingId|
+--------+------------------+------------------+-------------+
| 1 | 01/02/2009 10:00 | 01/02/2009 20:00 | 5 |
| 2 | 01/02/2009 2:00 | 01/02/2009 2:00 | 3 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 | 4 |
| 3 | 01/02/2009 2:00 | 01/02/2009 5:00 | 6 |
| 4 | 01/02/2009 3:03 | 01/02/2009 5:00 | 6 |
+--------+------------------+------------------+-------------+

如果您注意到结果中引用了示例数据的所有 6 行,尽管它只有 5 行。我相信,对于此数据,所有行在某一点或另一点相互重叠,重叠行数为 6。

为了得到这个结果,可以使用下面的查询:

SELECT COUNT (DISTINCT a.ColumnId)
FROM TimeTable AS a
JOIN TimeTable AS b ON ((a.InTime BETWEEN b.InTime AND b.OutTime)
OR (a.OutTime BETWEEN b.InTime AND b.OutTime)
OR (a.InTime < b.InTime AND a.OutIme > b.OutTime))
AND (a.ColumnId != b.ColumnId)

返回所有 6 行的计数。

关于sql - SQL Server 中的重叠时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2037618/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com