SELECT *
FROM event
WHERE EXISTS
(
SELECT 1
FROM dual
WHERE MOD(start_date - TO_DATE(1, 'J') + level - 1, 7) = 6
CONNECT BY
level <= end_date - start_date + 1
)
Die Unterabfrage Iterierten alle Tage von start_date
zu end_date
, prüft jeden Tag, und wenn es eine Monday
ist, kehrt 1
.
Sie können diese Abfrage für komplexere Bedingungen verlängern: überprüfen, ob ein Ereignis auf ANY Monday OR Friday 13th
fällt, zum Beispiel:
SELECT *
FROM event
WHERE EXISTS (
SELECT 1
FROM dual
WHERE MOD(start_date - TO_DATE(1, 'J') + level - 1, 7) = 6
OR (MOD(start_date - TO_DATE(1, 'J') + level - 1, 7) = 3 AND TO_CHAR(start_date + level - 1, 'DD') = '13')
CONNECT BY
level <= end_date - start_date + 1
)
Bitte beachte, dass ich MOD(start_date - TO_DATE(1, 'J') + level - 1, 7)
statt TO_CHAR('D')
verwenden. Dies liegt daran, dass TO_CHAR('D')
von NLS_TERRITORY
beeinflusst wird und nicht für die Überprüfung eines bestimmten Wochentages verwendet werden sollte.
Diese Abfrage verwendet keine Indizes und führt immer einen vollständigen Tabellenscan durch. Aber das ist in diesem speziellen Fall kein Problem, da es sehr wahrscheinlich ist, dass ein gegebenes Intervall eine Monday
enthält.
Auch wenn die Intervalle 1
Tage lang sind, gibt der Index 14%
Werte zurück, wenn die Intervalle länger sind, sogar mehr.
Seit würde in diesem Fall ineffizient sein, und die innere Unterabfrage ist sehr schnell (es verwendet in-memory FAST DUAL
Zugriffsverfahren), das, denke ich, wird eine optimale Methode, sowohl durch Effizienz und Erweiterbarkeit sein.
Siehe Eintrag in meinem Blog für weitere Informationen:
Absolut richtig. Ich habe CONNECT BY vorher benutzt. – cpm
* nie * benutzt, das ist. – cpm