2012-11-07 53 views
1

這似乎是一個很簡單的問題,但我似乎無法現在就看着辦吧......選擇一條記錄,如果ID /名稱重複

下面是數據的簡化圖,我取從我目前存儲的proc:

ID  Name   Class  Desc 
--- -----  ------ ----- 
84  Calvin J. 2B 
53  Fred D.  3B 
53  Fred D.  ADJ  Change/Correction 
47  Mary F.  3A 
47  Mary F.  ADJ  New Product 
09  Donald M. ADJ  Cancelled 
21  Richard G. ADJ  Bad Debt 
21  Richard G. ADJ  Cancelled 

我需要修改我的過程,以選擇每個人只有一個記錄。如果某人進行了調整,我只想選擇帶有調整的記錄並忽略其他記錄。基於以上,這是我試圖返回的結果集:

ID  Name   Class  Desc 
--- -----  ------ ----- 
84  Calvin J. 2B 
53  Fred D.  ADJ  Change/Correction 
47  Mary F.  ADJ  New Product 
09  Donald M. ADJ  Cancelled 
21  Richard G. ADJ  Cancelled 

請幫助!

UPDATE

我才意識到,有此查詢的附加要求;如果有兩項調整,其中一項描述爲「壞賬」,另一項爲「已取消」,則需要選擇具有「已取消」描述的記錄(請參閱上面的更新數據)。

回答

0

這應該做的伎倆:

SELECT ID, Name, Class, [Desc] 
FROM (
    SELECT ID, Name, Class, [Desc], 
     ROW_NUMBER() OVER(PARTITION BY ID 
          ORDER BY CASE WHEN Class = 'ADJ' 
             THEN 0 ELSE 1 END) rn 
    FROM Table1 
) A 
WHERE rn = 1 

它看起來可怕比它確實是。內部查詢包含用ROW_NUMBER()計算的額外列。這是對你的行進行編號,從1開始,每個不同的ID(在PARTITION BY中指定)。 ORDER BY,告訴ROW_NUMBER()如何排序行,是一個case語句,說Class = 'ADJ'行應該在所有其他行之前。然後最後我們只抓取第1行。結果是選擇ADJ行,如果有一個是ID,或者是其他常規行。

編輯迴應更新的要求
如果您有其他優先標準,那麼你可以添加這些到ORDER BY,就像你在一個正常的查詢將ORDER BY。通常只需執行內部查詢,而不必過濾到rn = 1,這樣您就可以準確查看如何分配行號。

下面是更新查詢應滿足您的新的要求:

SELECT ID, Name, Class, [Desc] 
FROM (
    SELECT ID, Name, Class, [Desc], 
     ROW_NUMBER() OVER(PARTITION BY ID 
          ORDER BY 
          CASE WHEN Class = 'ADJ' 
            THEN 0 ELSE 1 END, 
          CASE WHEN [Desc] = 'Cancelled' 
            THEN 0 ELSE 1 END) rn 
    FROM Table1 
) A 
WHERE rn = 1 

See it in action here.

+0

嗨乍得,感謝您的答覆。但是這對我仍然沒有意義。如果我爲class ='ADJ'的行指定了rn,並且在我的where子句中選擇了rn = 1,那麼我將永遠不會在我的結果集中看到它們,因爲如您所述,「我們只抓取1行」。 – 8thWonder

+0

好問題 - 0或1實際上不是rn。對於每個「ID」,ROW_NUMBER()從1開始並計數2,3,4等。0或1告訴「ROW_NUMBER()」如何排序行。如果ADJ有一排,那麼它將出現在沒有ADJ的行之前,因此被編號爲1. – Chad

+0

乍得,根據您給出的解釋,您的解決方案應該可以工作,但不幸的是我仍然沒有獲得期望的記錄。 – 8thWonder