Het is verbazingwekkend dat niemand dit al bijna twee jaar heeft opgemerkt, maar de andere antwoorden zijn allemaal fout omdat ze geen rekening hielden met het geval dat zowel de startdatum als de einddatum buiten het bereik van het zoekbereik vallen. Beschouw dit als het bereik van de datum:
start_date <<---------------------------- date range --------------------------->> end_date
En dit is het bereik van onze zoekopdracht:
start_date <<---------------------------- date range --------------------------->> end_date
start_search <<-------- search range -------->> end_search
De zoekopdracht zou ons een positief resultaat moeten opleveren omdat ze elkaar kruisen. Maar als u de andere antwoorden gebruikt, krijgt u een negatief resultaat omdat geen van beide start_date
noch end_date
is tussen start_search
en end_search
.
Laten we alle 4 mogelijke modi tekenen om de oplossing te krijgen van kruising:
start_date <<---------- date range --------------------------->> end_date start_search <<------------------------- search range -------->> end_search
start_date <<---------------------------- date range ---------->> end_date start_search <<---------- search range ------------------------>> end_search
start_date <<---------------------------- date range --------------------------->> end_date start_search <<-------- search range -------->> end_search
start_date <<----------- date range -------->> end_date start_search <<------------------------- search range ------------------------>> end_search
U kunt OR
alle 4 mogelijke gevallen om de eenvoudige oplossing te verkrijgen:
select*from table where
/* 1st case */ start_date between start_search and end_search
or /* 2nd case */ end_date between start_search and end_search
or /* 3rd case */ (start_date <= start_search and end_date >= end_search)
or /* 4th case */ (start_date >= start_search and end_date <= end_search)
/* the 4th case here is actually redundant since it is being covered by the 1st and 2nd cases */
Een minder directe oplossing is:
select*from table where start_date between start_search and end_search /* covers 1st and 4th cases */ or start_search between start_date and end_date /* covers 2nd and 3rd cases */
Probeer het te visualiseren met behulp van de bovenstaande diagrammen.
Als we proberen een patroon te extrapoleren uit de 4 diagrammen hierboven, kunnen we zien dat tijdens een kruising,end_date
is altijd >= start_search
, en aan de andere kant, start_date
is altijd <= end_search
. Als we verder visualiseren, kunnen we zien dat wanneer die twee voorwaarden gelden, we geen kruispunt kunnen hebben . Als zodanig is een andere oplossing zo eenvoudig als:
select*from table where
end_date >= start_search && start_date <= end_search
En het voordeel van deze oplossing is dat we maar 2 vergelijkingen nodig hebben. Vergelijk dat met de "OR
alles"-benadering die 2 tot wel 8 (3 + 3 + 2) vergelijkingen vereist. (Elke between
oproep bestaat uit 3 vergelijkingen
.)