如何避免获取重复信息?

时间:2011-10-17 08:15:19

标签: sql sql-server tsql

我有两张桌子......

CustomerId, Name   
1           pete
2           dave
3           jon


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

我希望select以下列格式返回数据

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

基本上当我查看包含数百条记录的select时,我希望能够只看到客户,然后在列表中看到它们之后的所有角色,并返回null,其中coumn引用的表中没有重复项。

2 个答案:

答案 0 :(得分: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)因为我喜欢使用它们而不是直接编写嵌套查询: - )

答案 1 :(得分: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
相关问题