2017-06-13 49 views
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 

這裏是我的結果的一個樣本:

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

解決您的加入使用現代JOIN語法,而不是古老的過時的A,B連接語法。這應該使錯誤更清晰,更容易被發現。 –

+0

你能解釋一下這個問題嗎?我看到你已經解釋了你所做的並顯示了結果數據,但是我看不到任何問題,也沒有結果問題。 –

+0

我試圖將結果限制爲每個用戶一行:當前用戶名,第一個以前的用戶名,第二個以前的用戶名。現在,連接正在提取用戶名,第一個用戶名和第二個用戶名。它還返回用戶名,第二用戶名和第一用戶名的第二行。這有意義嗎? – 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 (+) 

解釋:你有兩個AltID444455554444 <> 5555爲真,5555 <> 4444也是如此。因此,您現有的條件....

OldNames1.ON_AltID <> OldNames2.O2_AltID (+) 

....產生交叉連接,所以你得到兩個記錄。由於5555 < 4444爲false,因此更改條件以加入不足交叉連接。

+0

外連接,這樣仍然會產生2行:1111-4444-5555和1111-5555-null。 –