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
)
サブクエリを反復start_date
からend_date
へのすべての日、毎日チェックし、それがMonday
だ場合、1
を返します。
あなたは簡単に、より複雑な条件のために、このクエリを拡張することができます。例えば、イベントがANY Monday OR Friday 13th
に当たるかどうかを確認します。私は代わりにTO_CHAR('D')
のMOD(start_date - TO_DATE(1, 'J') + level - 1, 7)
を使用
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
)
注意を。これは、TO_CHAR('D')
がNLS_TERRITORY
の影響を受けるため、特定の曜日のチェックに使用しないでください。
このクエリはインデックスを使用せず、常にフルテーブルスキャンを実行します。しかし、この特定のケースでは問題はありません。特定の間隔にMonday
が含まれる可能性が高いためです。
間隔が1
日であっても、間隔がさらに長い場合は、インデックスは14%
の値を返します。
この場合、は効率が悪く、内部サブクエリは非常に高速です(メモリ内でFAST DUAL
アクセス方式を使用しています)ので、これは効率と拡張性の両方で最適な方法になると思います。
は詳細のための私のブログのエントリを参照してください。
を絶対に正しいです。以前はCONNECT BYを使っていました。 – cpm
* never * used、つまりです。 – cpm