2016-11-01 23 views
0

日付の値を "より大きい"または "より小さい"条件と比較して3つのテーブルをクエリします。しかし、私はこれについてSQLを書いていません。日付比較の表には、開始日と終了日の2つの日付の範囲ではなく、フィールドのみがあります。テーブルは以下のとおりです。SQL - 他のテーブルの値に基づく範囲の比較に基づくテーブルの結合/参照テーブル

staff_roster - 月のスタッフの日々のレコードを含む大きなテーブル:

staff_no | store | r_date 
---------------------------- 
sf001 | A | 1/10/2016 
sf001 | A | 2/10/2016 
sf001 | A | 3/10/2016 
sf001 | A | 4/10/2016 
sf001 | A | 5/10/2016 
sf001 | A | 6/10/2016 
sf001 | A | 7/10/2016 
sf001 | A | 8/10/2016 
    .... 
sf002 | A | 1/10/2016 
sf002 | A | 2/10/2016 
    .... 

staff_posmove - 条件を探したテーブル:

staff_no | p_date | previous_pos | new_pos 
--------------------------------------------------- 
sf001 | 3/10/2016 | Jr sales  | clerk 
sf001 | 6/10/2016 | clerk  | Sr sales 

staff_profile

staff_no | position 
--------------------- 
sf001 | Sr sales 
sf002 | Jr sales 

テーブル「staff_roster」の列には、次のような結果が表示されます。他の2つのテーブルに依存する追加の列「位置」がn個あります。

ロジックは次のとおりです。各staff_roster.r_dateをテーブル "staff_posmove"の "p_date"と比較します。システムが「r_date」が「p_date」より小さい同じスタッフを見つけた場合、「position」の値は「previous_pos」になります。それ以上であれば、値として "new_pos"を取る。

しかし、問題は「staff_posmove」に複数のレコードが存在する可能性があり、重複した条件が存在するため、重複した結果と間違った結果になります。一例として

テイクsf001は、私の予想結果は次のとおりです。

staff_no | store | r_date | position 
----------------------------------------- 
sf001 | A | 1/10/2016 | Jr sales 
sf001 | A | 2/10/2016 | Jr sales 
sf001 | A | 3/10/2016 | clerk 
sf001 | A | 4/10/2016 | clerk 
sf001 | A | 5/10/2016 | clerk 
sf001 | A | 6/10/2016 | Sr sales 
sf001 | A | 7/10/2016 | Sr sales 
sf001 | A | 8/10/2016 | Sr sales 
.... 

さらに、システムは比較のために、スタッフの「staff_posmove」のレコードが見つからない場合は、「位置」は、テーブルをルックアップする必要があり「staff_profile "結果に関連するスタッフの位置を入れて "位置":

staff_no | store | r_date | position 
----------------------------------------- 
sf002 | A | 1/10/2016 | Jr sales 
sf002 | A | 2/10/2016 | Jr sales 
.... 

私が何かしようとした" THEN VARCHARとして(b.previous_posをキャストCASE a.staff_no = b.staff_noとa.r_date < b.p_dateを(10))でも、依然として間違った結果が得られます。質問は少し長いかもしれませんが、あなたが助けてくれることを願っています。

答えて

1

この問題を解決する典型的な方法は、OUTER APPLYを使用することです。 最初にレコードがないため、これは難しくなります。staff_posmoveには最初のレコードがありません。この問題を解決するには

、常に次のことは、各スタッフのための最初のレコードを考慮して、位置を選択するselectのロジックを使用しています。

select r.*, 
     (case when pm.p_date < r_date then pm.new_pos else pm.old_pos end) as position 
from staff_roster r outer apply 
    (select top 1 pm.* 
     from (select pm.*, 
        row_number() over (partition by staff_no order by p_date) as seqnum 
      from staff_posmove pm 
      ) pm 
     where p_date < r_date or seqnum = 1 -- always ensure first row is considered 
     order by pm.p_date desc 
    ) pm 
+0

ありがとうと私はこの声明の詳細を勉強します。 –

0

これはテストされていません。

以下各名簿の後の最初の動きを与える(それゆえ、私たちは前の仕事を取る)する必要があります

Select 
r.staff_no, r.store_, r.r_date, p.previous_job 
from staff_roster r left join staff_posmove p 
on p.staff_no = r.staff_no and r_date < p_date 
where row_number() over (partition by r.staff_no, r_date order by p_date) =1 

をそして、我々は上の残りを取るために、それにstaff_profile追加以下のようになります。

Select 
p.staff_no, r.store_, r.r_date, nvl(m.previous_job,p.position) 
from staff_profile p join staff_roster r 
on p.staff_no = r.staff_no 
left join staff_posmove m 
on m.staff_no = r.staff_no and r.r_date < m.p_date 
where row_number() over (partition by r.staff_no, r.r_date order by m.p_date) =1 
+0

私はちょっとした文章を編集してみるだけです。 SQLサーバーの場合、nvl - > isnullです。WHERE句にエラーが発生しました:「ウィンドウ関数はSELECT句またはORDER BY句にしか現れません。 –

関連する問題