2009-04-08 13 views
6

Mam tabelę zdarzeń, która określa zakres dat z polami start_date i end_date. Mam inny zakres dat określony w kodzie, który definiuje bieżący tydzień jako "week_start" i "week_end".Jak ustalić, czy zakres dat występuje w dowolnym czasie w innym zakresie dat?

Chciałbym przetestować wszystkie wydarzenia w tym tygodniu. Przypadki wydają się być: zaczyna

  • Event i kończy się w ciągu tygodnia
  • Event rozpoczyna się przed tygodniem, ale kończy się w ciągu tygodnia
  • Event rozpoczyna się w ciągu tygodnia, ale kończy się po tygodniu
  • impreza rozpoczyna się przed tygodniem, a także kończy się po tygodniu
  • zdarzenia, które nie przebywają wewnątrz, ani zachodzić na tydzień w ogóle są ignorowane

Próbuję wymyślić zapytanie, które może obsłużyć wszystkie te przypadki. Do tej pory udało mi się zdobyć tylko te przypadki, które zajmują tygodniowy okres nakładania się lub zdarzenia, które są w pełni wewnętrzne; Zasadniczo zbyt wiele zapisów lub wcale.

+0

To jest duplikat http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap, który ma rygorystyczne wyprowadzenie prostego (tylko 2 warunki) rozwiązania. –

Odpowiedz

21
(event.start BETWEEN week.start AND week.end) 
OR 
(week.start BETWEEN event.start AND event.end) 

W prostych słowach albo tydzień rozpoczyna się podczas wydarzenia, albo wydarzenie zaczyna się w ciągu tygodnia.

Niech to sprawdzić: zaczyna

Event i kończy się w

Impreza rozpoczyna się w ciągu tygodnia na tydzień.

Event rozpoczyna się przed tygodniem, ale kończy się

Tydzień rozpoczyna się w trakcie imprezy tygodnia.

Event rozpoczyna się w ciągu tygodnia, ale kończy się po

Impreza rozpoczyna się w ciągu tygodnia na tydzień.

Event rozpoczyna się przed tygodniem, a także kończy się po

Tydzień rozpoczyna się w trakcie imprezy tygodnia.

Należy zauważyć, że w wyrażeniach powyżej BETWEEN używa się tylko ze względu na zwięzłość.

Strict wyrażenie wygląda następująco:

(event.start >= week.start AND event.start < week.end) 
OR 
(week.start >= event.start AND week.start < event.end) 

, pod warunkiem, że week.end jest week.start + INTERVAL 7 DAY.

I. e. jeśli ty tydzień rozpoczyna się od Sun, 0:00:00, to powinno zakończyć się na next Sun, 0:00:00 (nie na Sat, 0:00:00)

Wyrażenie to wygląda bardziej skomplikowany niż ten, który jest powszechnie używany:

event.start < week.end AND event.end > week.start 

, ale ta pierwsza jest bardziej wydajny i przyjazny dla indeksu.

Zobacz te artykuły w moim blogu do porównań wyników:

+1

Pomiędzy tutaj jest tylko dla zwięzłości. Z reguły koniec tygodnia powinien być mniej rygorystyczny. – Quassnoi

+0

Szkoda, że ​​to nie rozwiąże problemu wydarzeń, które zaczynają się przed tygodniem i kończą po tygodniu. –

+0

@Pop Catalin: Naprawdę? Czy dany tydzień nie rozpoczyna się w trakcie imprezy? – Quassnoi

3

Można napisać swój stan tak:

start_date <= week_end AND end_date >= week_start 

Edit: ten zakłada data_początkowa < = end_date i week_start < = week_end (są odpowiednio uporządkowane) i daje najlepszą wydajność w większości implementacji db powodu nie używania lub (co w niektórych bazach danych może stworzyć problemy z wydajnością)

Edit2 : to rozwiązanie rozwiązuje również problem zdarzeń, które rozpoczynają się przed przerwą i końcem po interwale.

+1

Znacznie ładniejsze rozwiązanie niż pomiędzy porównaniem przedziałów czasowych –

0

W celu ...

where start_date >= week_start and end_date <= week_end 
where start_date <= week_start and end_date >= week_start and end_date <= week_end 
where start_date >= week_start and start_date <= week_end and end_date > week_end 
where start_date < week_start and end_date > week_end 
0

(koniec 2> = Start 1) & & (start2 < = koniec 1) Myślę, że wróci prawdziwe dla dowolnych przecinających zakresów dat.

Znalazłem dyskusję na temat tego here, która okazała się przydatna.

2

+1 za pop Catalin, ale niestety nie mam uprawnień do głosowania.

Wymagany stan ograniczenia to tylko standardowy sposób wyrażenia operatora "OVERLAPS" Allena.

Dodatkowe zastrzeżenie SQL: jeśli end_date ma wartość NULL, należy traktować wartości null w tych kolumnach jako "koniec czasu".

Dodatkowe zastrzeżenie funkcjonalne: pamiętaj, aby dostosować użycie "< =" versus '<', czy rejestrowane okresy zawierają datę końcową czy nie.