Устранить частичные повторяющиеся строки из набора результатов - PullRequest
2 голосов
/ 08 апреля 2009

У меня есть запрос, который возвращает набор результатов, аналогичный приведенному ниже (на самом деле он намного больше, тысячи строк):

     A    | B  | C  |    D
     -----|----|----|-----
1    NULL | d0 | d0 | NULL
2    NULL | d0 | d1 | NULL
3    NULL | d0 | d2 |   a0
4      d0 | d1 | d1 | NULL
5      d0 | d2 | d2 |   a0

Две строки считаются дубликатами, 1 и 2, потому что A, B и D одинаковы. Чтобы устранить это, я мог бы использовать SELECT DISTINCT A, B, D, но тогда я не получаю столбец C в моем наборе результатов. Столбец C является необходимой информацией для строк 3, 4 и 5.

Итак, как мне перейти от набора результатов к этому (результат, отображаемый в C4, также может быть NULL вместо d1):

     A    | B  | C    | D
     -----|----|------|-----
1    NULL | d0 | NULL | NULL
3    NULL | d0 | d2   |   a0
4      d0 | d1 | d1   | NULL
5      d0 | d2 | d2   |   a0

Ответы [ 5 ]

5 голосов
/ 08 апреля 2009
DECLARE @YourTable TABLE (
  A VARCHAR(2)
  , B VARCHAR(2)
  , C VARCHAR(2)
  , D VARCHAR(2))

INSERT INTO @YourTable VALUES (NULL, 'd0', 'd0', NULL)
INSERT INTO @YourTable VALUES (NULL, 'd0', 'd1', NULL)
INSERT INTO @YourTable VALUES (NULL, 'd0', 'd2', 'a0')
INSERT INTO @YourTable VALUES ('d0', 'd1', 'd1', NULL)
INSERT INTO @YourTable VALUES ('d0', 'd2', 'd2', 'a0')


SELECT A, B, C = MIN(C), D
FROM @YourTable
GROUP BY A, B, D

SELECT A, B, CASE WHEN MIN(C) = MAX(C) THEN MIN(C) ELSE NULL END, D
FROM @YourTable
GROUP BY A, B, D

SELECT A, B, CASE WHEN MIN(COALESCE(C, 'dx')) = MAX(COALESCE(C, 'dx')) THEN MIN(C) ELSE NULL END, D
FROM @YourTable
GROUP BY A, B, D
2 голосов
/ 08 апреля 2009

Используйте Dense_Rank () для разделения по A, B и D
(Спасибо, Ливен, за запрос временной таблицы, мне пришлось использовать его для демонстрации, чтобы быть последовательным;))

Согласно MSDN ,

Ранг строки равен единице плюс количество различных рангов, предшествующих рассматриваемому ряду

Разделение по A, B, C, а затем сортировка по A, B, C, D даст вам ранг 1 для первого отличного значения, где уникальность определяется A, B, D. Вот откуда пришла фильтрация по 1.

где DenseRank = 1

Вот результат

alt text

Вот код:

DECLARE @YourTable TABLE (
  A VARCHAR(2)
  , B VARCHAR(2)
  , C VARCHAR(2)
  , D VARCHAR(2))

INSERT INTO @YourTable VALUES (NULL, 'd0', 'd0', NULL)
INSERT INTO @YourTable VALUES (NULL, 'd0', 'd1', NULL)
INSERT INTO @YourTable VALUES (NULL, 'd0', 'd2', 'a0')
INSERT INTO @YourTable VALUES ('d0', 'd1', 'd1', NULL)
INSERT INTO @YourTable VALUES ('d0', 'd2', 'd2', 'a0')

;with DistinctTable as (
    select  *, 
    DenseRank = Dense_Rank() over (Partition By A, B, D order by A, B, C, D)
    from    @YourTable
)
select  A, B, C, D
from    DistinctTable
where   DenseRank = 1
0 голосов
/ 08 апреля 2009

Тот факт, что у вас есть NULL в A и D, усложняет ситуацию для любых СУЩЕСТВ.

Любое решение MIN / MAX на C может не дать вам NULL, как я думаю, вы хотите. В противном случае используйте MIN (C) и простую группу по.

Сначала вы должны извлечь уникальные ключи (A, B, D), а затем использовать их, чтобы определить, извлекать строки снова и понять, что делать с C

DECLARE @TheTable TABLE (
  A varchar(2) NULL,
  B varchar(2) NULL,
  C varchar(2) NULL,
  D varchar(2) NULL
)

INSERT INTO @TheTable VALUES (NULL, 'd0', 'd0', NULL)
INSERT INTO @TheTable VALUES (NULL, 'd0', 'd1', NULL)
INSERT INTO @TheTable VALUES (NULL, 'd0', 'd2', 'a0')
INSERT INTO @TheTable VALUES ('d0', 'd1', 'd1', NULL)
INSERT INTO @TheTable VALUES ('d0', 'd2', 'd2', 'a0')

SELECT DISTINCT
    T.A,
    T.B,
    CASE Number WHEN 1 THEN T.C ELSE NULL END,
    T.D
FROM
    (SELECT
        COUNT(*) AS Number,
        A, B, D
    FROM
        @TheTable
    GROUP BY
        A, B, D
    ) UQ
    JOIN
    @TheTable T ON ISNULL(T.A, '') = ISNULL(UQ.A, '') AND ISNULL(T.B, '') = ISNULL(UQ.B, '') AND ISNULL(T.D, '') = ISNULL(UQ.D, '')
0 голосов
/ 08 апреля 2009

если у вас есть уникальный идентификатор в таблице, то я бы пошел что-то вроде этого:

SELECT A,B,C,D FROM table WHERE id IN (SELECT DISTINCT A,B,D)

Проблема в том, что вы всегда получите первое значение C, а не первое со значением.

0 голосов
/ 08 апреля 2009

Возможно подзапрос?

ВЫБРАТЬ A, B, C, D ИЗ таблицы1, ГДЕ ЕСТЬ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...