2009-05-07 20 views
3

を使用して日付の範囲内に曜日を検索:次のテーブル構造としたOracle SQL

Event: 
    id: integer 
    start_date: datetime 
    end_date: datetime 

週の特定の日に秋のイベントのすべてを照会する方法はありますか?たとえば、月曜日に発生するすべてのイベントを検索するクエリを探したいとします。 start_dateまたはend_dateが月曜日に該当するかどうかを調べていますが、その間の日付を調べる方法がわかりません。

ここではストアドプロシージャに対するバイアスがあるので、純粋なSQLが推奨されています。これはRailsコンテキストから呼び出されていますが、これはストアドプロシージャも処理しないからです。

答えて

6
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アクセス方式を使用しています)ので、これは効率と拡張性の両方で最適な方法になると思います。

は詳細のための私のブログのエントリを参照してください。

+0

を絶対に正しいです。以前はCONNECT BYを使っていました。 – cpm

+0

* never * used、つまりです。 – cpm

1

これは、より簡単にそれを行う必要があります。

select * 
from event 
where 2 between to_number(trim(to_char(start_date,'D'))) 
      and to_number(trim(to_char(end_date,'D'))) 
    or (end_date - start_date) > 6 
+0

01.01.2003(水曜日)をSTART_DATEに、01.01.2004(木曜日)をEND_DATEとして配置すると、このクエリは何も返しません。そして、これらの日の間に月曜日は確かにあります。 – Quassnoi

+0

あなたは正しいです、ありがとう。私は今それを修正しました... – JosephStyons

関連する問題