2017-02-08 3 views
0

これは私の最初の投稿ですので、詳細が必要な場合はお知らせください。あるテーブルのグループ化された結果を別のテーブルのLEFT JOINの状態で使用する

私は3つのテーブルを持ち、そのうちの1つはセットアップテーブル[invrules]であり、残りの2つはメンバデータテーブル[basic][invinst]です。私がしたいのは、[invinst].[invcde][invinst].[instamt]の列をそのスキームに固有の値を使って表示することです。 [invrules]テーブルのフィールド[schkey]の最初の4文字にスキームコードがあります。私がしようとしているのは、そのスキームのためにそれらをグループ化し、それをそれぞれに結びつけることによってこれらが何であるかを判断することです。LEFT JOIN私は私にカラムを与えるように作成しました。これは実行に非常に長い時間がかかり、明らかにそれほど効率的ではありません。

CTEや関数を使用するのではなく、SELECTというステートメントでこれを行う必要があります。私は[invinst]表はに参加する必要がないので、代わりにCROSS JOINを使用しようとした

select getdate() DateRun 
    ,b.membno 
    ,b.surnam 
    ,b.scheme 
    ,i1.invcde AS 'Investment Code 1' 
    ,i1.instamt AS 'Investment Percentage 1' 
    ,i2.invcde AS 'Investment Code 2' 
    ,i2.instamt AS 'Investment Percentage 2' 
    ,i3.invcde AS 'Investment Code 3' 
    ,i3.instamt AS 'Investment Percentage 3' 
from basic AS b 
left join 
(
    select i.invcde, RANK() OVER (ORDER BY i.invcde) AS [RANK] 
    from invrules AS i 
    where left(schkey, 4) = 'ABCD' 
    and (i.enddte is null or i.enddte > getdate()) 
    group by i.invcde 
) AS [invcde_list_1] ON [invcde_list_1].Rank = 1 
left join 
(
    select i.invcde, RANK() OVER (ORDER BY i.invcde) AS [RANK] 
    from invrules AS i 
    where left(schkey, 4) = 'ABCD' 
    and (i.enddte is null or i.enddte > getdate()) 
    group by i.invcde 
) AS [invcde_list_2] ON [invcde_list_2].Rank = 2 
left join 
(
    select i.invcde, RANK() OVER (ORDER BY i.invcde) AS [RANK] 
    from invrules AS i 
    where left(schkey, 4) = 'ABCD' 
    and (i.enddte is null or i.enddte > getdate()) 
    group by i.invcde 
) AS [invcde_list_3] ON [invcde_list_3].Rank = 3 
left join invinst AS i1 on b.membno = i1.membno and i1.invcde = [invcde_list_1].invcde and i1.contsrc = 'EE' and i1.enddte is null and [invcde_list_1].Rank = 1 
left join invinst AS i2 on b.membno = i2.membno and i2.invcde = [invcde_list_2].invcde and i2.contsrc = 'EE' and i2.enddte is null and [invcde_list_2].Rank = 2 
left join invinst AS i3 on b.membno = i3.membno and i3.invcde = [invcde_list_3].invcde and i3.contsrc = 'EE' and i3.enddte is null and [invcde_list_3].Rank = 3 
where b.membno >= 15000 
and b.scheme = 'ABCD' 
order by b.membno 

は、これは正しい結果を提供するために長い時間がかかった試み(数分)でした何でもこれは、[invinst]テーブルから派生した列にNullという値を与えたCROSS JOINのために、各行の[basic]テーブルと一致するデータと[invinst]テーブルの一致データを返しました。私はそれを匿名化するために、多少のデータを変更しなければならなかったが、うまくいけば、あなたは私が達成しようとしているかを理解します

[basic] 
membno surnam scheme 
14000 Jones ABCD 
15000 Smith ABCD 
15001 Henry ABCD 
15002 Mabel ABCD 
15003 McDonald ABCD 

[invinst] 
membno contsrc invcde instamt 
14000 EE CD01 100 
15000 EE CD01 50 
15000 EE CD02 50 
15000 ER CD01 50 
15001 EE CD02 100 
15002 EE CD01 100 
15003 EE CD01 100 
15003 ER CD01 100 

[invrules] 
schkey contsrc enddte invcde 
ABCDCAT1 EE  CD01 
ABCDCAT1 ER  CD01 
ABCDCAT1 EE  CD02 
ABCDCAT1 ER  CD02 
ABCDCAT1 EE  CD03 
ABCDCAT1 ER  CD03 
ABCDCAT2 EE  CD01 
ABCDCAT2 ER  CD01 
ABCDCAT2 EE  CD02 
ABCDCAT2 ER  CD02 
ABCDCAT2 EE  CD03 
ABCDCAT2 ER  CD03 
ABCDCAT3 EE  CD01 
ABCDCAT3 EE  CD02 
ABCDCAT3 EE  CD03 
ABCDCAT4 EE  CD01 
ABCDCAT4 EE  CD02 
ABCDCAT4 EE  CD03 
ABBBCAT1 EE  CD01 
ABBBCAT1 EE  CD02 
ABBBCAT2 EE  CD01 
ABBBCAT3 EE  CD01 

select getdate() DateRun 
    ,b.membno 
    ,b.surnam 
    ,b.scheme 
    ,i1.invcde AS 'Investment Code 1' 
    ,i1.instamt AS 'Investment Percentage 1' 
    ,i2.invcde AS 'Investment Code 2' 
    ,i2.instamt AS 'Investment Percentage 2' 
    ,i3.invcde AS 'Investment Code 3' 
    ,i3.instamt AS 'Investment Percentage 3' 
from basic AS b 
cross join 
(
    select i.invcde, RANK() OVER (ORDER BY i.invcde) AS [RANK] 
    from invrules AS i 
    where left(dcschkey, 4) = 'ABCD' 
    and (i.enddte is null or i.enddte > getdate()) 
    group by i.invcde 
) AS [invcde_list] 
left join invinst AS i1 on b.membno = i1.membno and i1.invcde = [invcde_list].invcde and i1.contsrc = 'EE' and i1.enddte is null and [invcde_list].Rank = 1 
left join invinst AS i2 on b.membno = i2.membno and i2.invcde = [invcde_list].invcde and i2.contsrc = 'EE' and i2.enddte is null and [invcde_list].Rank = 2 
left join invinst AS i3 on b.membno = i3.membno and i3.invcde = [invcde_list].invcde and i3.contsrc = 'EE' and i3.enddte is null and [invcde_list].Rank = 3 
where b.membno >= 15000 
and b.scheme = 'ABCD' 
order by b.membno 

これは、いくつかのテストデータである:これは、コードでした。

多くのサブクエリを使用しないと、スキームの[invrules]テーブルを要約してより効率的なLEFT JOINの中で使用する方法がありますか?それとも別のアプローチがありますか?

おかげで、

ダレル

+0

ピボットの良いケースのように見えますが、よりシンプルで消化しやすい例から始めたいと思うかもしれません。 –

+0

Aaronに感謝します。ピボットが私をどのように助けてくれるのかを探るつもりです。 –

答えて

-1

あなたは順番に「invrules」で連結されている「invinst」と「基本」に参加したくない場合 - その後、単にそう!

ネストした結合を使用します。「フラット」ではありません。

基本的に、最初の3つの結合は何も結合しません。


UPD:正確に動作していないことがあり、この

SELECT getdate() AS DateRun, 
    member_no 
    member_surname, 
    scheme, 
    investment_code, 
    investment_percentage, 
    percentage_rank 
FROM (
    SELECT 
     b.membno AS member_no, 
     b.surnam AS member_surname, 
     b.scheme AS scheme, 
     i.invcde AS Investment_Code, 
     i.instamt AS Investment_Percentage, 
     RANK() OVER (PARTITION BY b.membno ORDER BY i.instamt) AS percentage_rank 
    FROM basic AS b 
     LEFT JOIN invinst AS i ON b.membno = i.membno 
      LEFT JOIN invcde_list AS il ON i.invcde = il.invcde 
     WHERE b.membno >= 15000 
      AND b.scheme = 'ABCD' 
      AND i.contsrc = 'EE' 
      AND i1.enddte IS NULL   
    ) as FinallyJoined 
WHERE percentage_rank < 4; 

ような何かをしようと、私は到達してMSSQLを持っていない - しかし、私はあなたのアイデアを得たいと考えています。

+0

ありがとうございます。ユリ、あなたはinvinstジョインのネストされたジョインを意味しますか?私は、それがinvrulesテーブルを繰り返しているように見えるので、それぞれにネストされたジョインを持つよりもエレガントな方法があるかどうかはわかりませんでした。便利な簡単な例があれば、ありがとう。 –

+0

クエリは結合されたテーブルから複数の行を持ちますが、OPは*行ではなく別の*列*として表示されるように思われます。 –

+0

Darrell、私が言ったことは、実際にinvinstを使ってinvinstに参加しています。そして、そのjoinに基本的に参加してください - 少なくとも、それはあなたのルール(b.membno = i1.membnoとi1.invcde = [invcde_list_1] .invcde)suggest エンジンにとってはより明確にし、これらの結合を適切な順序で並べることが理にかなっています。 次に、混乱レベルが低下するにつれて、それはさらに考えるのがより簡単になります。 あなたがしようとしていることはリレーショナルモデルには適していませんが。 1つではなく3つのレコードを取得してみませんか? –

関連する問題