2011-10-17 58 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