2012-03-20 14 views
0

私は現在、私がデバッグの過程にいる手続きを持っており、このselect文に絞っています。where節のcaseを正しく使用する方法

注:to_date( '')、3300,5220は、パラメータから来るものの表現です。

さて、これが行うことに仮定されたものを、オフセットのタイムスタンプであるパラメータを取ると、オフセット値

を引くことは、週の初めからによって行っている分の数です深夜の日曜日= 0です(したがって、真夜中の場合、オフセットは1440になります)。

オフセットをパラメータから差し引くと、曜日の先頭になります。次に、すでに設定されているテーブルからオフセット値を取得し、その値を週の先頭に追加してタイムスタンプを取得します。

これは、シフトの開始日と終了日を取得するために行われます。

私の元のコードは問題なく動作しますが、日曜日に入る土曜日の境界条件がありません。

SELECT SHIFT_ID_PK, SHIFT_NAME_FK, 
     SHIFT_START_DAY, SHIFT_START_TIME, 
     SHIFT_END_DAY, SHIFT_END_TIME, 
     SITE_ID_FK, SHIFT_DAY_ID, 
     STARTOFFSET, ENDOFFSET, 
     TO_TIMESTAMP_TZ(TO_CHAR((PSTARTTIMESTAMP - (VSTARTOFFSET/24/60)) + (STARTOFFSET/24/60), 'YYYY-MM-DD HH:MI:SS AM'), 'YYYY-MM-DD HH:MI:SS AM TZH:TZM') as SHIFT_START_DATE, 
     TO_TIMESTAMP_TZ(TO_CHAR((PENDTIMESTAMP - (VENDOFFSET/24/60)) + (ENDOFFSET /24/60), 'YYYY-MM-DD HH:MI:SS AM') ,'YYYY-MM-DD HH:MI:SS AM TZH:TZM') as SHIFT_END_DATE 
    from shift_tbl 
    WHERE 
     ENDOFFSET >= VSTARTOFFSET 
    and STARTOFFSET < VENDOFFSET 
    order by shift_start_date asc; 

この境界条件を処理するために私が思いついたのは、以下で私がスクリプトでテストしたものです。

declare 
    VSTARTOFFSET integer; 
    VENDOFFSET integer; 
    SHIFTOFFSET integer; 
    PSTARTTIMESTAMP timestamp; 
    PENDTIMESTAMP timestamp; 
    begin 
    VSTARTOFFSET := 10020; 
    VENDOFFSET := 420; 
    PSTARTTIMESTAMP := TO_DATE('3/17/2012 23:00', 'mm/dd/yyyy hh24:mi'); 
    PENDTIMESTAMP := TO_DATE('3/18/2012 7:00', 'mm/dd/yyyy hh24:mi'); 

    SELECT SHIFT_ID_PK, SHIFT_NAME_FK, 
     SHIFT_START_DAY, SHIFT_START_TIME, 
     SHIFT_END_DAY, SHIFT_END_TIME, 
     SITE_ID_FK, SHIFT_DAY_ID, 
     STARTOFFSET, ENDOFFSET, 
     TO_TIMESTAMP_TZ(TO_CHAR((PSTARTTIMESTAMP - (VSTARTOFFSET/24/60)) + (STARTOFFSET/24/60), 'YYYY-MM-DD HH:MI:SS AM'),'YYYY-MM-DD HH:MI:SS AM TZH:TZM') as SHIFT_START_DATE, 
     TO_TIMESTAMP_TZ(TO_CHAR((PENDTIMESTAMP- (VENDOFFSET/24/60)) + (ENDOFFSET /24/60), 'YYYY-MM-DD HH:MI:SS AM'),'YYYY-MM-DD HH:MI:SS AM TZH:TZM') AS SHIFT_END_DATE 
    from SHIFT_TBL 
    where 
    case 
     when SHIFT_START_DAY = 7 and SHIFT_END_DAY = 1 then   
       SHIFTOFFSET:= ENDOFFSET + 10080; 
      and VENDOFFSET := VENDOFFSET + 10080; 
     else 
       SHIFTOFFSET := ENDOFFSET; 
    end 
       SHIFTOFFSET >= VSTARTOFFSET 
      and STARTOFFSET < VENDOFFSET 
    order by SHIFT_START_DATE asc; 
    end; 

ご覧のとおり、where句のcase文をどのように処理するかはわかりません。基本的には、開始日が土曜日で、終了日が日曜日の場合、終了オフセット/販売オフセットに10080(1週間)を追加し、その条件を満たさない場合は元の値を使用します。

基本的に私の質問はかなり簡単です...私は信じていますが、私は解決策を得ることが困難です。だから私が知りたいのは、where節の中でcase文を適切に使う方法です。そして、where句の中でこのフォームのcase文を使用することを想定していないのであれば、このselect文をどのくらい正確に設定すればよいでしょうか。

ご意見やご提案は大変ありがとうございます。 ありがとうございます。

+0

これは不必要に複雑に思えますが、多分私は何かを見逃しています。基本的に、開始と終了のタイムスタンプを計算しようとしていますが、このデータテーブルにタイムスタンプが格納されていないと仮定します。私はあなたの日のフィールドが整数であることを確認します。日曜日は1から土曜日は7です。シフトタイムフィールドにはどのようなデータが格納されていますか? –

+0

SQL WHERE句内にPL/SQL代入文を実行することはできません。 – GriffeyDog

答えて

3

:それは次のようになります。 あなたがしたいのは、取得したい行を記述する正しい論理述語(真または偽を返す式)を書くことです。

  1. CASEなし::CASEと

    WHERE 
    (SHIFT_START_DAY = 7 and SHIFT_END_DAY = 1 AND ENDOFFSET + 10080 >= VSTARTOFFSET and STARTOFFSET < VENDOFFSET + 10080) OR 
    (NOT (SHIFT_START_DAY = 7 and SHIFT_END_DAY = 1) AND SHIFTOFFSET >= VSTARTOFFSET and STARTOFFSET < VENDOFFSET) 
    
  2. WHERE 
    (CASE WHEN SHIFT_START_DAY = 7 and SHIFT_END_DAY = 1 THEN ENDOFFSET + 10080 ELSE ENDOFFSET END) >= VSTARTOFFSET 
    AND STARTOFFSET < (CASE WHEN SHIFT_START_DAY = 7 and SHIFT_END_DAY = 1 THEN VENDOFFSET + 10080 ELSE VENDOFFSET END) 
    

    は、ここで私は(私の知る限り、あなたの要件を理解して)それを定義しようとする方法を2例であり、

私はデバッグしませんでした表現はそうであると期待していません;)しかし、私はあなたが考えを持っていることを願っています。

+0

これはまさに私が探していたものです!私はちょうどこれをキャッチしないように真剣な脳のおならを持っていたと思います。ありがとう! – James213

0

WHERE句に変数を設定するのではなく、基本クエリをカーソルに置き、それを使用してループ内でメインクエリを駆動することをお勧めします。これにより、各反復のクエリの外に変数を設定することができます。あなたも、あなたがそれを行うことはできません実際には、WHERE句で任意の変数を設定する必要はありません

declare 
--variables 
cursor c_shifts is 
select SHIFT_ID_PK, SHIFT_START_DAY, SHIFT_END_DAY 
from SHIFT_TBL; 
begin 
for r_result in c_shifts 
loop 
if r_result.SHIFT_START_DAY = 1 and r_result.SHIFT_END_DAY = 7 then 
    --set variables to values for special case shifts 
else 
    --set variables for all other cases 
end if; 
    --run your query for the particular result in this loop iteration based upon r_result.SHIFT_ID_PK, using the variables you set above 
    --save results to a staging table, directly dbms_output from the block, etc., as needed 
end loop; 
    --commit results if saving to a staging table, etc., as needed once the loop completes 
end; 
0

、クエリを計算しないでください:)

提案:私は補助カレンダーのテーブルを使用することを検討すべきであるのはなぜauxiliary calendar table

を使用して検討しましたか?

日付が含まれているビジネスモデル の周りのソリューションを開発するのがはるかに簡単になります。最後に私がチェックしたのは、 には、あなたが考えることができるほとんどのビジネスモデルが含まれており、 程度です。 xとyの間

  • どのように多くの営業日:冗長必要終わる定数の問題は、 複雑で非効率的な方法は、以下の質問が含まれていますか?

  • 4月の第2火曜日と第1金曜日の間の日付はすべて何ですか?おそらくa column for julianized business days

  • ... ...。

  • 関連する問題