SQL server中的重叠时间

SQL server中的重叠时间,sql,sql-server,logic,Sql,Sql Server,Logic,我有一张这样的桌子 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

我有一张这样的桌子

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点注销,因此第5次登录与第一次登录重叠。表中没有可用的索引

请给我问题的答案


我需要在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)
使用问题初始数据进行测试运行:

+--------+------------------+------------------+
|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 |
+--------+------------------+------------------+-------------+
+--------+------------------+------------------+-------------+
|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 |
+--------+------------------+------------------+-------------+
运行更新后的查询,我们得到以下结果:

+--------+------------------+------------------+-------------+
|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 |
+--------+------------------+------------------+-------------+
+--------+------------------+------------------+-------------+
|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

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

选择计数(不同的a.ColumnId)
从时间表上看
加入时间表为b ON((a.b.InTime和b.OutTime之间的时间)
或(a.在b.开始时间和b.结束时间之间的结束时间)
或者(a.InTimeb.OutTime))
和(a.ColumnId!=b.ColumnId)
返回所有6行的计数。

选择T1。ColumnId,T1.Intime,T1.OutTime
Select T1.*,T2.*
From Table1 T1
Inner Join Table1 T2 ON ((T1.InTime >= T2.InTime AND T1.OutTime > T2.InTime)
                         OR (T2.InTime >= T1.InTime AND T2.OutTime > T1.InTime)) 
                        AND (T1.ColumnId != T2.ColumnId)
从T1到T2 其中1=1 和(T2.Intime介于T1.Intime和T1.OutTime之间 或T2.T1.Intime和T1.OutTime之间的超时) 和T1.ColumnId T2.ColumnId
仔细测试解决方案,我发现目前发布的答案要么重叠检查错误,要么返回太多结果(每个重叠两行)

选择
aa.ColumnId作为ColumnIdA,aa.InTime作为InTimeA,aa.OutTime作为OutTimeA,
bb.ColumnId为ColumnIdB,bb.InTime为InTimeB,bb.OutTime为OutTimeB
从…起
MyTable aa
参加
aa.ColumnIdbb.暂停时间
在定义“重叠”时必须谨慎。我假设如果第一个周期是凌晨3点到凌晨4点,第二个周期是凌晨4点到凌晨5点,那么这些范围不会重叠。如果确实希望将这种情况视为重叠,请更改
where
子句中的
=


性能与行数的平方成正比。对于大型数据集,更快的解决方案是可能的,但比这个解决方案涉及的内容要多得多。

如果SQL兼容ansi 2003,则可以使用重叠函数。 注意t1.c1
SEL *
FROM TimeTable AS t1,TimeTable AS t2
WHERE (t1.Intime,t1.Outtime) OVERLAPS (t2.Intime,t2.Outtime)
AND t1.ColumnId < t2.ColumnId
ORDER BY 1;
SEL*
从时刻表t1开始,时刻表t2
其中(t1.Intime,t1.Outtime)重叠(t2.Intime,t2.Outtime)
t1.ColumnId
请学习高亮显示T-SQL语句或类似于此处的表格的行,然后使用编辑器工具栏上的“代码”按钮(101 010)正确设置其格式。否则你的问题真的很难阅读和理解!你们有关于“时间”和“休息时间”的索引吗?否则,当处理数百万行时,任何查询都将无效并超时……重叠检查是错误的。尝试T1.InTime=3am T1.OutTime=4am,T2.InTime=2am,T2.OutTime=5am。为每个重叠返回两行。不起作用。试试a.开始时间=凌晨2点,a.结束时间=凌晨5点,b.开始时间=凌晨3点,b.结束时间=凌晨4点。另外,为每个重叠返回两行。更正:为某些重叠返回两行,而不是全部。@Vladim K。在告诉您某些内容不起作用之前,请尝试运行一些测试。Paulo,我进行了测试,这就是我留下评论的原因。总的来说,执行的比较将是必要的两倍(连接条件需要是
a.ColumnId
a.ColumnId>b.ColumnId
,以解决此问题)。当一个范围与另一个范围完全吻合时,重叠测试会忽略这种情况。按照编码,这将导致每个部分重叠返回两行,每个完全重叠返回一行。在没有敌意的情况下,考虑一下这个结果的正确性和可取性。@ Vladmim K.我在这里不理解:“重叠测试忽略了一个范围完全符合另一个范围的情况。”为什么?如果某个范围的起始点位于另一个范围的边界内,则将验证比较并返回该行。但是我仍然没有看到ColumnId比较的问题。因为,例如,id#6有两个重叠,一个与#3重叠,另一个与#4重叠。。。该死!我刚刚注意到#3应该报告#2、#4和#6的行。它完全错过了最后一个!但我不认为每个重叠报告2或3行有任何错误。
SEL *
FROM TimeTable AS t1,TimeTable AS t2
WHERE (t1.Intime,t1.Outtime) OVERLAPS (t2.Intime,t2.Outtime)
AND t1.ColumnId < t2.ColumnId
ORDER BY 1;