2008-09-22 36 views
21

Tôi có hai bảng, cả hai đều có trường thời gian bắt đầu và thời gian kết thúc. Tôi cần phải tìm, cho mỗi hàng trong bảng đầu tiên, tất cả các hàng trong bảng thứ hai, nơi các khoảng thời gian giao nhau.Cách đơn giản và hiệu quả để tìm các hàng có chồng chéo theo thời gian trong SQL là gì?

Ví dụ:

  <-----row 1 interval-------> 
<---find this--> <--and this--> <--and this--> 

Hãy cụm từ câu trả lời của bạn trong hình thức của một SQL WHERE -clause, và xem xét các trường hợp thời gian kết thúc trong bảng thứ hai có thể NULL.

Nền tảng đích là SQL Server 2005, nhưng các giải pháp từ các nền tảng khác cũng có thể được quan tâm.

+2

bản sao có thể có của [Xác định xem có hai phạm vi ngày chồng chéo] (http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap) –

+0

Có lẽ, nếu thời gian kết thúc trong bảng thứ hai là NULL, nó phải được coi là 'chu kỳ không có thời gian kết thúc và tiếp tục trong tương lai'. Đó là câu trả lời được chấp nhận; nó là một cách giải thích thông thường, nhưng nó không phải là giải thích duy nhất có thể. –

Trả lời

49
SELECT * 
FROM table1,table2 
WHERE table2.start <= table1.end 
AND (table2.end IS NULL OR table2.end >= table1.start) 
+0

Lưu ý rằng nếu bắt đầu và kết thúc biểu thị các trường hợp trong thời gian, bạn có thể muốn loại bỏ sự bình đẳng khỏi các phép so sánh, nếu không hai dãy sẽ được coi là giao nhau ngay cả khi một đầu ở cùng một thời gian. –

+7

Chứng minh: Nếu hai khoảng thời gian không trùng lặp thì (s2> e1 || e2 e1 || e2 = s1). – Stanislav

2
select * from table_1 
right join 
table_2 on 
(
table_1.start between table_2.start and table_2.[end] 
or 
table_1.[end] between table_2.start and table_2.[end] 
or 
(table_1.[end] > table_2.start and table_2.[end] is null) 
) 

EDIT: Ok, đừng đi cho giải pháp của tôi, nó perfoms như shit. Giải pháp "where" nhanh hơn 14 lần. Rất tiếc ...

Một số thống kê: chạy trên một db với ~ 65000 bản ghi cho cả bảng 1 và 2 (không lập chỉ mục), có khoảng thời gian 2 ngày giữa bắt đầu và kết thúc cho mỗi hàng, chạy trong 2 phút trong SQLSMSE (không có đủ kiên nhẫn để chờ đợi)

Sử dụng tham gia: 8356 hàng trong vòng 2 phút

Sử dụng nơi: 115.436 hàng trong vòng 2 phút

1

Đó là âm thanh rất phức tạp cho đến khi bạn bắt đầu làm việc từ ngược lại. Dưới đây tôi minh họa CHỈ TRƯỜNG HỢP TỐT (không có chồng chéo)! xác định bởi những 2 điều kiện đơn giản, chúng tôi không có sự chồng chéo dao động nếu condA HOẶC condB là TRUE, vì vậy chúng tôi sẽ đảo ngược những: KHÔNG condA VÀ KHÔNG CondB, trong trường hợp của chúng tôi Tôi chỉ đảo ngược dấu hiệu (> trở thành < =)

/* 
|--------| A        \___ CondA: b.ddStart > a.ddEnd 
      |=========| B    / \____ CondB: a.ddS > b.ddE 
          |+++++++++| A  /
*/ 
--DROP TABLE ran 
create table ran (mem_nbr int, ID int, ddS date, ddE date) 
insert ran values 
(100, 1, '2012-1-1','2012-12-30'), ----\ ovl 
(100, 11, '2012-12-12','2012-12-24'), ----/ 
(100, 2, '2012-12-31','2014-1-1'), 
(100, 3, '2014-5-1','2014-12-14') , 

(220, 1, '2015-5-5','2015-12-14') , ---\ovl 
(220, 22, '2014-4-1','2015-5-25') , ---/ 
(220, 3, '2016-6-1','2016-12-16') 

select DISTINCT a.mem_nbr , a.* , '-' [ ], b.dds, b.dde, b.id 
FROM ran a 
join ran b on a.mem_nbr = b.mem_nbr   -- match by mem# 
       AND  a.ID <> b.ID   -- itself 
        AND  b.ddS <= a.ddE  -- NOT b.ddS > a.ddE  
        AND  a.ddS <= b.ddE  -- NOT a.ddS > b.ddE 
+0

ngày kết thúc có thể là rỗng: / –

Các vấn đề liên quan