Det er utroligt, at ingen har bemærket dette i næsten to år, men de andre svar er alle forkerte fordi de ikke tog højde for tilfældet, når både startdatoen og slutdatoen falder uden for rækkevidden af søgeområdet. Overvej, at dette er datointervallet:
start_date <<---------------------------- date range --------------------------->> end_date
Og dette er rækkevidden af vores søgning:
start_date <<---------------------------- date range --------------------------->> end_date
start_search <<-------- search range -------->> end_search
Søgningen skulle give os et positivt resultat, fordi de krydser hinanden. Men hvis du bruger de andre svar, vil du få et negativt resultat, fordi hverken start_date
heller ikke end_date
er mellem start_search
og end_search
.
For at finde løsningen, lad os tegne alle 4 mulige tilstande af kryds:
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
Du kan OR
alle 4 mulige tilfælde for at opnå den ligetil løsning:
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 */
En mindre ligetil løsning er:
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 */
Prøv at visualisere det ved hjælp af diagrammerne ovenfor.
Hvis vi forsøger at ekstrapolere et mønster ud af de 4 diagrammer ovenfor, kan vi se, at under et kryds,end_date
er altid >= start_search
, og på bagsiden, start_date
er altid <= end_search
. Hvis vi visualiserer yderligere, kan vi se, at når disse to betingelser gælder, kan vi ikke ikke have et kryds . Som sådan er en anden løsning så enkel som:
select*from table where
end_date >= start_search && start_date <= end_search
Og fordelen ved denne løsning er, at vi kun behøver 2 sammenligninger. Sammenlign det med "OR
alt" tilgang, som kræver fra 2 op til så meget som 8 (3 + 3 + 2) sammenligninger. (Hver between
opkaldet består af 3 sammenligninger
.)