SQL ВЫБРАТЬ только 1 столбец, если в другом столбце есть дубликат - PullRequest
0 голосов
/ 18 марта 2020

Для начала позвольте мне сказать, что у меня есть права на чтение только для нашей базы данных.

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

Пример

Row | col1 | col2 | col3 | col4 | col5 |

1   | AA   | BB   | CC   | AA   | CC   |
2   | DD   | CC   | DD   | BB   | BB   |
3   | ZZ   | ZZ   | CC   | CC   | BB   |
4   | AA   | AA   | DD   | AA   | AA   |

Я пытаюсь выбрать только уникальные значения в строках

1| AA | BB | CC 
2| DD | CC | BB
3| ZZ | CC | BB 
4| AA | DD |   

Я действительно не уверен, с чего начать. Кинда поставлена ​​в тупик на этом.

Ответы [ 4 ]

1 голос
/ 18 марта 2020

Похоже, вам понадобится отключить данные, получить DENSE_RANK, а затем повторить:

WITH YourTable AS(
    SELECT *
    FROM (VALUES(1,'AA','BB','CC','AA','CC'),
                (2,'DD','CC','DD','BB','BB'),
                (3,'ZZ','ZZ','CC','CC','BB'),
                (4,'AA','AA','DD','AA','AA'))V([Row],Col1,Col2,Col3,Col4,Col5)),
Unpvt AS(
    SELECT YT.[Row],
           V.Col,
           DENSE_RANK() OVER (PARTITION BY YT.[Row] ORDER BY V.Col) AS DR
    FROM YourTable YT
         CROSS APPLY (VALUES(YT.Col1),
                            (YT.Col2),
                            (YT.Col3),
                            (YT.Col4),
                            (YT.Col5))V(Col))
SELECT U.[Row],
       MAX(CASE U.DR WHEN 1 THEN U.Col END) AS Col1,
       MAX(CASE U.DR WHEN 2 THEN U.Col END) AS Col2,
       MAX(CASE U.DR WHEN 3 THEN U.Col END) AS Col3,
       MAX(CASE U.DR WHEN 4 THEN U.Col END) AS Col4,
       MAX(CASE U.DR WHEN 5 THEN U.Col END) AS Col5
FROM Unpvt U
GROUP BY U.[Row];
0 голосов
/ 18 марта 2020

Если 2016+ и у вас есть многочисленные или переменные столбцы

Пример

Declare @YourTable Table ([Row] varchar(50),[col1] varchar(50),[col2] varchar(50),[col3] varchar(50),[col4] varchar(50),[col5] varchar(50))  Insert Into @YourTable Values 
 (1,'AA','BB','CC','AA','CC')
,(2,'DD','CC','DD','BB','BB')
,(3,'ZZ','ZZ','CC','CC','BB')
,(4,'AA','AA','DD','AA','AA')

Select *
 From  (
        Select A.[Row]
              ,B.* 
         From  @YourTable A
         Cross Apply (
                        Select [Value] 
                              ,ColNr = concat('Col',dense_rank() over (order by value))
                         From  OpenJson( (Select A.* For JSON Path,Without_Array_Wrapper ) ) 
                         Where [Key] not in ('Row')
                     ) B
      ) src
 Pivot (max(Value) for ColNr in ([Col1],[Col2],[Col3],[Col4],[Col5]) ) pvt

Возвращает

Row Col1    Col2    Col3    Col4    Col5
1   AA      BB      CC      NULL    NULL
2   BB      CC      DD      NULL    NULL
3   BB      CC      ZZ      NULL    NULL
4   AA      DD      NULL    NULL    NULL
0 голосов
/ 18 марта 2020

Это очень нехорошо, потому что кто-то рассматривал таблицу SQL как электронную таблицу, действуя так, как будто строки и столбцы - это одно и то же. Вот один подход, который создает решение:

declare @t table (Row int, col1 char(2), col2 char(2), col3 char(2), col4 char(2), col5 char(2))
insert into @t(Row,col1,col2,col3,col4,col5) values
(1,'AA','BB','CC','AA','CC'),
(2,'DD','CC','DD','BB','BB'),
(3,'ZZ','ZZ','CC','CC','BB'),
(4,'AA','AA','DD','AA','AA')

select * from (
select Row,Foo,'col' + CONVERT(varchar(10),ROW_NUMBER() OVER (PARTITION BY Row ORDER BY Bar)) as Bar2  from (
select Row,Foo,Bar from (
select
    *,ROW_NUMBER() OVER (PARTITION BY Row,Foo ORDER BY Bar) rn
from @t
unpivot (Foo for Bar in (col1,col2,col3,col4,col5)) u
) v
where rn = 1
) w
) x
pivot (MAX(Foo) for Bar2 in (col1,col2,col3,col4,col5)) y
0 голосов
/ 18 марта 2020

Это немного сложно, но вы можете использовать apply и условное агрегирование:

select t.row, c.*
from t cross apply
     (select max(case when seqnum = 1 then col end) as col1,
             max(case when seqnum = 2 then col end) as col2,
             max(case when seqnum = 3 then col end) as col3,
             max(case when seqnum = 4 then col end) as col4,
             max(case when seqnum = 5 then col end) as col5
      from (select col,
                   row_number() over (order by min(pos)) as seqnum
            from (values (1, t.col1), (2, t.col2), (3, t.col3), (4, t.col4), (5, t.col5))
                 ) v(pos, col)
            group by col
      ) c;
...