MS SQL Объединение 5 столбцов в 3 столбца - PullRequest
1 голос
/ 25 февраля 2020

Я пытаюсь понять, как объединить 5 столбцов в 3 столбца и избежать дублирования одновременно. Я думал об этом в течение нескольких дней и пока не могу найти какое-либо решение, поэтому я решил попросить о помощи здесь.

По сути, сейчас мы используем 5 столбцов в нашей базе данных, скажем так A, B, C, D, E и кто-то из нашей компании решил, что мы перенесем эту информацию в новые 3 столбца, назовем их NEW_1, NEW_2, NEW_3, потому что нет случаев, когда у нас было бы больше 3 значения в строке в БД.

Мне нужно каким-то образом извлечь эти 5 столбцов и получить их всего в 3 столбца, не повторяя их.

Here is an example of how it should probably look

Пока что я Я думал и пытался использовать CASE, но я не могу понять, как остановить показ одного и того же значения во всех 3 новых столбцах. Я думал о назначении некоторых переменных, чтобы определить, какие столбцы пропустить в выбранном CASE, но я обнаружил, что я не могу сделать это таким образом.

Если кто-то может хотя бы направить меня в нужное русло, я был бы очень признателен.

SELECT CASE 
    WHEN A is not null THEN A
    WHEN B is not null THEN B
    WHEN C is not null THEN C
    WHEN D is not null THEN D
    WHEN E is not null THEN E
    ELSE NULL
END as NEW_1,
CASE 
    WHEN B is not null THEN B
    WHEN C is not null THEN C
    WHEN D is not null THEN D
    WHEN E is not null THEN E
    ELSE NULL
END as NEW_2,
CASE 
    WHEN C is not null THEN C
    WHEN D is not null THEN D
    WHEN E is not null THEN E
    ELSE NULL
END as NEW_3

Ответы [ 2 ]

6 голосов
/ 25 февраля 2020

Вот вариант, где мы разворачиваем данные и затем применяем условное агрегирование в CROSS APPLY

Пример

Declare @YourTable Table ([A] varchar(50),[B] varchar(50),[C] varchar(50),[D] varchar(50),[E] varchar(50))
Insert Into @YourTable Values 
 (1,2,3,NULL,NULL)
,(NULL,4,NULL,5,NULL)
,(NULL,null,6,7,8)
,(9,NULL,NULL,NULL,NULL)

Select A.*
      ,B.* 
 From  @YourTable A
 Cross Apply ( 
  Select Val1 = max(case when ColNr=1 then Value end)
        ,Val2 = max(case when ColNr=2 then Value end)
        ,Val3 = max(case when ColNr=3 then Value end)
    From (
          Select ColNr = row_number() over (order by Seq)
                ,B1.*
           From  (values (1,A)
                        ,(2,B)
                        ,(3,C)
                        ,(4,D)
                        ,(5,E)
                   ) B1(Seq,Value)
            Where Value is not null
         ) B2
    ) B

Возвращает

enter image description here

Просто для удовольствия, вот XML версия

Select A.*
      ,Val1 = XMLData.value('/x[1]','varchar(max)')
      ,Val2 = XMLData.value('/x[2]','varchar(max)')
      ,Val3 = XMLData.value('/x[3]','varchar(max)')
 From  @YourTable A
 Cross Apply ( values ( convert(xml,
                        concat('<x>'+A+'</x>'
                              ,'<x>'+B+'</x>'
                              ,'<x>'+C+'</x>'
                              ,'<x>'+D+'</x>'
                              ,'<x>'+E+'</x>'
                              ) ) ) ) B(XMLData)
1 голос
/ 25 февраля 2020

Мне нравится ответ Джона, и, вероятно, он лучше моего, но вот немного другая версия, если столбцы зафиксированы с указанным c числом.

Создайте строку значений столбцов с разделителями, затем используйте xml для извлечения 1-го, 2-го, 3-го значений.

Declare @YourTable Table ([A] varchar(50),[B] varchar(50),[C] varchar(50),[D] varchar(50),[E] varchar(50));
Insert Into @YourTable Values 
 (1,2,3,NULL,NULL),(NULL,4,NULL,5,NULL),(NULL,null,6,7,8),(9,NULL,NULL,NULL,NULL);

WITH CTE AS (
SELECT CASE WHEN a IS NULL THEN '' ELSE a + '~' END +
       CASE WHEN b IS NULL THEN '' ELSE b + '~' END +
       CASE WHEN c IS NULL THEN '' ELSE c + '~' END +
       CASE WHEN d IS NULL THEN '' ELSE d + '~' END +
       CASE WHEN e IS NULL THEN '' ELSE e + '~' END AS Combined
FROM @YourTable
)
SELECT
ISNULL(CAST(N'<x>' + REPLACE(Combined, '~', N'</x><x>') + N'</x>' AS XML).value('/x[1]', 'nvarchar(max)'), '') [new_1],
ISNULL(CAST(N'<x>' + REPLACE(Combined, '~', N'</x><x>') + N'</x>' AS XML).value('/x[2]', 'nvarchar(max)'), '') [new_2],
ISNULL(CAST(N'<x>' + REPLACE(Combined, '~', N'</x><x>') + N'</x>' AS XML).value('/x[3]', 'nvarchar(max)'), '') [new_3]
FROM CTE;

enter image description here

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