2011-10-17 81 views
0

我有兩個表...如何避免重複信息?

CustomerId, Name 
1   pete 
2   dave 
3   jon 


CustomerId, Role 
1   1 
1   2 
2   1 
3   2 
3   3 

而且我想,當我看一個選擇數以百計的記錄,我想選擇以下列格式返回數據

Name, Role 
pete 1 
null 1 
dave 2 
jon 2 
null 3 

基本上能夠僅查看客戶,然後查看列表中的所有角色,並在coumn引用的表中沒有重複的情況下返回null。

+1

不明白期望的結果是如何得到的。 –

+0

我也不這樣多數民衆贊成爲什麼我發佈它在論壇上:-) – Exitos

+0

我的意思是你用什麼邏輯來定義你想要的結果?我不清楚爲什麼'角色= 1'有'皮特,null'但'角色= 2'有'戴夫,jon'(我看到答案你接受的回報從你說的話你想反正不同的東西!) –

回答

1
-- TEST DB PREPARATION!!! 

DROP TABLE #Names 
DROP TABLE #Roles 

CREATE TABLE #Names 
(
    CustomerId INT, 
    Name VARCHAR(1000) 
) 

CREATE TABLE #Roles 
(
    CustomerId INT, 
    Role Int 
) 

INSERT INTO #Names VALUES (1, 'pete') 
INSERT INTO #Names VALUES (2, 'dave') 
INSERT INTO #Names VALUES (3, 'jon') 

INSERT INTO #Roles VALUES (1, 1) 
INSERT INTO #Roles VALUES (1, 2) 
INSERT INTO #Roles VALUES (2, 1) 
INSERT INTO #Roles VALUES (3, 2) 
INSERT INTO #Roles VALUES (3, 3) 

-- HERE BEGINS THE REAL CODE!!! 

; WITH Base AS 
(
    SELECT #Names.CustomerId, Name, Role, ROW_NUMBER() OVER (PARTITION BY #Names.CustomerId ORDER BY Role) RN FROM #Names INNER JOIN #Roles ON #Names.CustomerId = #Roles.CustomerId 
) 

SELECT CustomerId, CASE WHEN RN = 1 THEN Name END Name, Role FROM Base 

我使用ROW_NUMBER()來爲名稱編號,並且只爲第一個(RN = 1)編寫名稱。我使用CTEWITH... AS),因爲我喜歡使用它們而不是直接嵌套查詢:-)

+0

這是一個偉大的解決方案,謝謝很多我要弄清楚這些分區如何工作,並在我的查詢中使用它... – Exitos

+0

只是一個快速問題,但爲什麼你使用#tablename,而不僅僅是tablename? – Exitos

+0

@ Pete2k因爲我在SQL服務器上創建臨時表來運行測試。這樣我就不用再拖了。以'#'開頭的表是本地臨時表。請閱讀http://msdn.microsoft.com/en-us/library/ms174979.aspx – xanatos

0

在這裏你去:

DECLARE @t TABLE 
(
id INT, 
Name VARCHAR(20), 
Role INT 
) 

INSERT INTO @t 
    SELECT ROW_NUMBER() OVER(ORDER BY Names.CustomerID, Roles.Role), Names.Name, Roles.Role 
    FROM @names AS Names 
     INNER JOIN @roles AS Roles ON Roles.CustomerId = Names.CustomerId 

UPDATE @t 
SET Name = NULL 
FROM @t Temp1 
WHERE EXISTS(SELECT TOP 1 1 FROM @t Temp2 WHERE Temp2.Name = Temp1.Name AND Temp2.id < Temp1.id) 

SELECT * FROM @t 

更換@Names@Roles與表定義。

你也可以用temp tablesrecursive CTEcursors做到這一點,但一個簡單的表變量將會很好。

僅供參考,我的測試代碼:

DECLARE @names TABLE 
(
CustomerId INT, 
Name VARCHAR(20) 
) 

DECLARE @roles TABLE 
(
CustomerId INT, 
Role INT 
) 

INSERT INTO @names VALUES (1, 'pete'), (2, 'dave'), (3, 'jon') 

INSERT INTO @roles VALUES (1, 1), (1, 2), (2, 1), (3, 2), (3,3) 

-- rest of query 

我的結果與你不同,我懷疑你有一個錯字與第一nulldave被周圍交換交換:

Name, Role 
pete 1 
null 2 
dave 1 
jon 2 
null 3 

編輯:已經想過這個問題,你其實可以不用臨時表做它在所有:

SELECT CASE WHEN row_no = 1 THEN Name ELSE NULL END AS Name, Role 
FROM 
(
SELECT ROW_NUMBER() OVER(PARTITION BY Names.CustomerID ORDER BY Names.CustomerID, Roles.Role) As row_no, Names.Name, Roles.Role FROM @names AS Names 
INNER JOIN @roles AS Roles ON Roles.CustomerId = Names.CustomerId 
) x