为每个不为空的特定列带来一行,其中包含列名

Bring a row for each specific column that is not empty, with the column name

我有这个 table 和以下数据:

ID 数据1 数据2 数据3 数据4 数据5 数据6 随机信息
1 测试 1 测试2 测试3 信息1
2 测试5 测试6 测试7 信息2
3 测试8 测试9 测试10 测试 11 信息3

我想要的结果table应该如下:

ID 数据 随机信息
1 数据1 信息1
1 数据3 信息1
1 数据5 信息1
2 数据2 信息2
2 数据4 信息2
2 数据6 信息2
3 数据1 信息3
3 数据2 信息3
3 数据5 信息3
3 数据6 信息3

有人可以帮我解决这个问题吗?

您可以将 CROSS APPLYVALUES 配合使用 UNPIVOT 您的数据

Select A.ID
      ,B.Data
      ,A.RandomInformation
 From  YourTable A
 Cross Apply ( values ('Data1',Data1)
                     ,('Data2',Data2)
                     ,('Data3',Data3)
                     ,('Data4',Data4)
                     ,('Data5',Data5)
                     ,('Data6',Data6)
             ) B(Data,Value)
 Where B.Value is not null

在SQL服务器中,你也可以使用UNPIVOT来做这个。即:

DECLARE @myTable TABLE
  (
    ID                INT
  , Data1             VARCHAR(50)
  , Data2             VARCHAR(50)
  , Data3             VARCHAR(50)
  , Data4             VARCHAR(50)
  , Data5             VARCHAR(50)
  , Data6             VARCHAR(50)
  , RandomInformation VARCHAR(50)
  );

INSERT INTO @myTable(ID, Data1, Data2, Data3, Data4, Data5, Data6, RandomInformation)
VALUES(1, 'Test1', NULL, 'Test2', NULL, 'Test3',NULL, 'Information1')
    , (2, NULL, 'Test5', NULL, 'Test6', NULL, 'Test7', 'Information2')
    , (3, 'Test8', 'Test9', NULL, NULL, 'Test10', 'Test11', 'Information3');

SELECT d.ID, d.x, d.RandomInformation, d.Data 
FROM
(SELECT ID, Data1, Data2, Data3, Data4, Data5, Data6, RandomInformation FROM @myTable) t 
UNPIVOT
(
   [Data] FOR x IN (Data1, Data2, Data3, Data4, Data5, Data6)
) AS d;

如果您不想提及列名,这里有一个更动态的方式:

SELECT t.id, t.RandomInformation, b.[Key] AS data 
FROM tablename t 
CROSS APPLY (SELECT * 
             FROM OPENJSON((SELECT t.* FROM tablename FOR JSON PATH,WITHOUT_ARRAY_WRAPPER))) b 
WHERE b.[Key] NOT IN ('ID', 'RandomInformation')

灵感来自 John Cappelletti