Dette er et klassisk problem, og det er faktisk nemmere, hvis du vender logikken om.
Lad mig give dig et eksempel.
Jeg vil poste en periode her, og alle de forskellige variationer af andre perioder, der overlapper på en eller anden måde.
|-------------------| 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
på den anden side, lad mig poste alle dem, der ikke overlapper:
|-------------------| compare to this one
|---| ends before
|---| starts after
Så hvis du blot reducerer sammenligningen til:
starts after end
ends before start
så finder du alle dem, der ikke overlapper, og så finder du alle de perioder, der ikke matcher.
For dit sidste IKKE I LIST-eksempel kan du se, at det matcher disse to regler.
Du skal beslutte, om de følgende perioder er I eller UDEN FOR dine områder:
|-------------|
|-------| equal end with start of comparison period
|-----| equal start with end of comparison period
Hvis din tabel har kolonner kaldet range_end og range_start, her er nogle simple SQL til at hente alle de matchende rækker:
SELECT *
FROM periods
WHERE NOT (range_start > @check_period_end
OR range_end < @check_period_start)
Bemærk IKKE derinde. Da de to simple regler finder alle de ikke-matchende rækker, vil en simpel NOT vende den for at sige:hvis det ikke er en af de ikke-matchende rækker, skal det være en af de matchende .
Anvender du simpel vendingslogik her for at slippe af med NOT, og du ender med:
SELECT *
FROM periods
WHERE range_start <= @check_period_end
AND range_end >= @check_period_start