查找与同一表中的其他条目重叠的所有条目的最有效方法是什么?每个条目都有一个开始和结束日期。例如,我有以下数据库设置:
CREATE TABLE DEMO
(
DEMO_ID int IDENTITY ,
START date NOT NULL ,
END date NOT NULL
);
INSERT INTO DEMO (DEMO_ID, START, END) VALUES (1, '20100201', '20100205');
INSERT INTO DEMO (DEMO_ID, START, END) VALUES (2, '20100202', '20100204');
INSERT INTO DEMO (DEMO_ID, START, END) VALUES (3, '20100204', '20100208');
INSERT INTO DEMO (DEMO_ID, START, END) VALUES (4, '20100206', '20100211');
我的查询如下:
SELECT DISTINCT *
FROM DEMO A, DEMO B
WHERE A.DEMO_ID != B.DEMO_ID
AND A.START < B.END
AND B.START < A.END
问题是当我的演示表有例如20'000行时,查询花费的时间太长。我的环境是MS SQL Server 2008。 感谢您提供更有效的解决方案
答案 0 :(得分:0)
您可以稍微重写一下查询:
SELECT A.DEMO_ID, B.DEMO_ID
FROM DEMO A, DEMO B
WHERE A.DEMO_ID != B.DEMO_ID
AND A.START >= B.START
AND A.START <= B.END
删除DISTINCT关键字可能会使事情变得更便宜,因为Sql Server会对返回的列(当您使用DISTINCT *时都是这样做)进行排序以消除重复项。
您还应该考虑添加索引。在Sql Server 2008中,我建议使用包含DEMO_ID的START,END索引。
答案 1 :(得分:0)
使用函数或存储过程:
首先,订购按开始和结束
的条目DECLARE @t table (
Position int identity(1,1),
DEMO_ID int,
START date NOT NULL ,
END date NOT NULL
)
INSERT INTO @t (DEMO_ID, START, END)
SELECT DEMO_ID, START, END
FROM DEMO
ORDER BY START, END
然后检查上一个和下一个记录的重叠:
SELECT t.DEMO_ID
FROM @t t INNER JOIN @t u ON t.Position + 1 = u.Position
WHERE u.Start <= t.End
UNION
SELECT t.DEMO_ID
FROM @t t INNER JOIN @t u ON t.Position - 1 = u.Position
WHERE t.Start <= u.End
您需要衡量以确保更快。在任何情况下,我们都不会将所有记录的日期字段与所有其他记录进行比较,因此对于大型数据集来说这可能会更快。
答案 2 :(得分:0)
这更简单,并且在超过20000条记录的约2秒内执行
select * from demo a
where not exists(
select 1 from demo b
where a.demo_id!=b.demo_id
AND A.S < B.E
AND B.S < A.E)
答案 3 :(得分:0)
迟到的答案,但想知道这是否会有所帮助:
create index IXNCL_Demo_DemoId on Demo(Demo_Id)
select a.demo_id, b.demo_id as [CrossingDate]
from demo a
cross join demo b
where a.[end] between b.start and b.[end]
and a.demo_id <> b.demo_id