Как мне избежать дублирования информации? - PullRequest
0 голосов
/ 17 октября 2011

У меня есть две таблицы ...

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

В основном, когда я смотрю на выбор с сотнямизаписи, которые я хочу, чтобы я мог видеть только клиента, а затем все роли после него в списке и возвращать ноль, если в таблице нет дубликатов, на которые ссылается Кумн.

Ответы [ 2 ]

1 голос
/ 17 октября 2011
-- 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) я «пишу» имя. Я использую CTE (WITH... AS), потому что я люблю использовать их вместо того, чтобы писать непосредственно вложенные запросы: -)

0 голосов
/ 17 октября 2011

Вот, пожалуйста:

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 tables или recursive CTE или cursors, но простая табличная переменная подойдет.

Для справки мой тестовый код:

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

Мои результаты отличаются от ваших, так как я подозреваю, что у вас произошла замена опечатки при первой замене null и dave:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...