2017-06-13 6 views
1

こんにちは:ユーザーにリンクされているメインIDコードを持つテーブルからデータを取得していますが、ユーザーが名前を変更するたびに余分なレコードが追加されます。私は、現在のユーザーと過去に使用していた古い名前のリストを取得しようとしています。私は外部結合を使用して、少なくとも1つの元の名前と1つの余分な元の名前を取得しています。ここSQLクエリから冗長データを削除する方法

select 
PrimaryName.PM_PDM, 
PrimaryName.PM_ID, 
PrimaryName.PM_AltID, 
PrimaryName.PM_Change, 
PrimaryName.PM_FName, 
PrimaryName.PM_LName, 
OldNames1.ON_PDM, 
OldNames1.ON_Change, 
OldNames1.ON_ID, 
OldNames1.ON_AltID, 
OldNames1.ON_FName, 
OldNames1.ON_LName, 
OldNames2.O2_PDM, 
OldNames2.O2_Change, 
OldNames2.O2_ID, 
OldNames2.O2_AltID, 
OldNames2.O2_FName, 
OldNames2.O2_LName 

from 
(select 
S_PDM as PM_PDM, 
S_ID as PM_ID, 
S_FIRST_NAME as PM_FName, 
S_LAST_NAME as PM_LName, 
S_CHANGE_IND as PM_Change, 
S_SURROGATE_ID as PM_AltID 
from S 
WHERE S_CHANGE_IND is null) PrimaryName, 

(select 
S_PDM as ON_PDM, 
S_ID as ON_ID, 
S_FIRST_NAME as ON_FName, 
S_LAST_NAME as ON_LName, 
S_CHANGE_IND as ON_Change, 
S_SURROGATE_ID as ON_AltID 
from S 
where S_CHANGE_IND = 'N') OldNames1, 

(select 
S_PDM as O2_PDM, 
S_ID as O2_ID, 
S_FIRST_NAME as O2_FName, 
S_LAST_NAME as O2_LName, 
S_CHANGE_IND as O2_Change, 
S_SURROGATE_ID as O2_AltID 
from S 
where S_CHANGE_IND = 'N') OldNames2 


where (OldNames1.ON_PDM = PrimaryName.pm_pdm) 
and 
    (OldNames1.ON_PDM = OldNames2.O2_PDM (+) 
    and 
    OldNames1.ON_AltID <> OldNames2.O2_AltID (+)) 

order by 2 

を私の結果のサンプルです:

はここにクエリの私はちょうど1行は3つの名前に対して返さ

PM_PDM |PM_ID |PM_ID2 |PM_CHANGE |PM_FNAME |PM_LNAME |ON_PDM |ON_CHANGE |ON_ID |ON_ID2 |ON_FNAME |ON_LNAME |O2_PDM  |O2_CHANGE |O2_ID2 |O2_ID |O2_FNAME |O2_LNAME 
1111 |2222 |3333 |   |Betty  |Boop  |1111 |N   |2222 |4444 |Betty  |Smith  |1111  |N   |5555 |2222 |Betty  |Jones 
1111 |2222 |3333 |   |Betty  |Boop  |1111 |N   |2222 |5555 |Betty  |Jones  |1111  |N   |4444 |2222 |Betty  |Smith 

  1. ベティ・ブープ2。ベティ・スミス3.ベティ・ジョーンズ

今、それは私はそれが最後の結合だけど、

  1. ベティブープ2.Bettyスミス3.Bettyジョーンズ
  2. ベティブープ2.Bettyジョーンズ3.Bettyスミス

を返しています私はそれを1行に制限する方法がわかりません。クエリは想定どおりに動作していますが、1行だけを返すように編集する必要があります。

+1

あなたは、現代のJOIN構文を使用する加入修正を古くから古くなったA、Bの代わりに構文を使用します。これにより、エラーをより明確にして見つけやすくなります。 –

+0

問題についても説明できますか?私はあなたが何をして結果データを表示したのかを見てきましたが、結果には何の疑問も問題も見当たりません。 –

+0

私は結果をユーザごとに1行に制限しようとしています:現在のユーザ名、最初の前のユーザ名、2番目の前のユーザ名。今すぐ、ユーザー名、最初のユーザー名と2番目のユーザー名を取得しています。また、User Name、Second User Name、First User Nameの2行目が返されます。これは理にかなっていますか? – Lyndey

答えて

1
row_number()を使用して、各変化に

割り当て番号とRN = 1RN = 2行のみ使用して二度、これらのデータを結合する:

with c as (select s.*, row_number() over (partition by pdm order by id desc) rn 
      from s where chg = 'N') 
select s.pdm, s.id, s.name, c1.id id1, c1.name name1, c2.id id2, c2.name name2 
    from (select * from s where chg is null) s 
    left join c c1 on c1.pdm = s.pdm and c1.rn = 1 
    left join c c2 on c2.pdm = s.pdm and c2.rn = 2 

テスト:

with s(pdm, id, chg, name) as (select 1, 1, 'N', 'Smith' from dual union all 
           select 1, 2, 'N', 'Jones' from dual union all 
           select 1, 3, null, 'Brown' from dual), 
    c as (select s.*, row_number() over (partition by pdm order by id desc) rn 
      from s where chg = 'N') 
select s.pdm, s.id, s.name, c1.id id1, c1.name name1, c2.id id2, c2.name name2 
    from  (select * from s where chg is null) s 
    left join c c1 on c1.pdm = s.pdm and c1.rn = 1 
    left join c c2 on c2.pdm = s.pdm and c2.rn = 2 


PDM ID NAME ID1 NAME1 ID2 NAME2 
--- --- ------ --- ------ --- ------ 
    1 3 Brown  2 Jones  1 Smith 
+0

この回答は良いスタートです。私はまだ一列で物事を取得する必要がありますが、そこに着いている。 – Lyndey

1

変更最後はこれに結合条件:

OldNames1.ON_AltID < OldNames2.O2_AltID (+) 

は説明:あなたは2つのAltID44445555を持っています。 4444 <> 5555が真であり、5555 <> 4444もそうです。したがって、あなたの既存の条件....

OldNames1.ON_AltID <> OldNames2.O2_AltID (+) 

....は、クロスジョイントを生成し、2つのレコードを取得します。より小さい値で結合する条件を変更すると、5555 < 4444がfalseなので、クロス結合がなくなります。

+0

外部結合。したがって、1111-4444-5555および1111-5555-nullの2行が生成されます。 –

関連する問題