Đây là một bài toán cổ điển và nó thực sự dễ dàng hơn nếu bạn đảo ngược logic.
Tôi sẽ cho bạn một ví dụ.
Tôi sẽ đăng một khoảng thời gian ở đây và tất cả các biến thể khác nhau của các khoảng thời gian khác trùng lặp theo một cách nào đó.
|-------------------| compare to this one
|---------| contained within
|----------| contained within, equal start
|-----------| contained within, equal end
|-------------------| contained within, equal start+end
|------------| not fully contained, overlaps start
|---------------| not fully contained, overlaps end
|-------------------------| overlaps start, bigger
|-----------------------| overlaps end, bigger
|------------------------------| overlaps entire period
mặt khác, hãy để tôi đăng tất cả những thứ không trùng lặp:
|-------------------| compare to this one
|---| ends before
|---| starts after
Vì vậy, nếu bạn đơn giản giảm so sánh thành:
starts after end
ends before start
sau đó bạn sẽ tìm thấy tất cả những khoảng thời gian không trùng nhau và sau đó bạn sẽ tìm thấy tất cả các khoảng thời gian không trùng khớp.
Đối với ví dụ NOT IN LIST cuối cùng của bạn, bạn có thể thấy rằng nó phù hợp với hai quy tắc đó.
Bạn sẽ cần phải quyết định thời kỳ sau ở TRONG hay NGOÀI phạm vi của bạn:
|-------------|
|-------| equal end with start of comparison period
|-----| equal start with end of comparison period
Nếu bảng của bạn có các cột được gọi là range_end và range_start, thì đây là một số SQL đơn giản để truy xuất tất cả các hàng phù hợp:
SELECT *
FROM periods
WHERE NOT (range_start > @check_period_end
OR range_end < @check_period_start)
Lưu ý KHÔNG ở đó. Vì hai quy tắc đơn giản tìm thấy tất cả các hàng không phù hợp , một KHÔNG đơn giản sẽ đảo ngược nó để nói: nếu nó không phải là một trong những hàng không khớp, nó phải là một trong những hàng phù hợp .
Áp dụng logic đảo ngược đơn giản ở đây để loại bỏ KHÔNG và bạn sẽ kết thúc với:
SELECT *
FROM periods
WHERE range_start <= @check_period_end
AND range_end >= @check_period_start