如何将第一行转换为列名?

时间:2019-05-02 18:19:53

标签: sql-server tsql azure-sql-database

我希望你一切都好。 我希望您在我拥有的数据转换任务上有所帮助。 我想将表的第一行转换为列名

我正在使用SQL Server Azure,并且每天从其他服务获取数据。

此服务将加载具有相同形式的表。

enter image description here

我想以相同的方式转换数据

enter image description here

您是否知道该怎么做?

2 个答案:

答案 0 :(得分:1)

解决此问题的方法是使用一些动态SQL魔术:

首先,创建并填充示例表(保存我们,以便您回答以后的问题):

DECLARE @T As Table
(
    Row_num int,
    Line nvarchar(4000)
);

INSERT INTO @T (Row_Num, Line) VALUES
(1, 'Col1;Col2;Col3'),
(2, 'Val1;Val2;Val3'),
(3, 'Value1;Value2;Value1'),
(4, 'Val A; val B;Val A'),
(5, 'Value A; Value B;Value C');

然后,构建一个并集所有查询,该查询从第一行中的每一行中选择值,但第一行中的分号(;)分隔符由用撇号({{1} }。在字符串前后添加撇号(这意味着我们将所有数据视为字符串):

,

接下来,使用'将第一个DECLARE @Sql nvarchar(max) = ''; SELECT @Sql += 'UNION ALL SELECT '''+ REPLACE(Line, ';', ''',''') + ''' ' FROM @T WHERE Row_Num > 1; 替换为公用表表达式声明,并在声明本身中指定列名称。请注意,这里我们不再需要撇号了,只需要用逗号替换分号即可:

stuff

最后,执行sql:

UNION ALL

结果:

SELECT @Sql = STUFF(@Sql, 1, 10, 'WITH CTE('+ REPLACE(Line, ';', ',') +') AS (') + ') SELECT * FROM CTE'
FROM @T 
WHERE Row_Num = 1;

You can see a live demo on rextester.

答案 1 :(得分:0)

另一种可能的方法是将文本数据转换为有效的JSON数组,然后将OPENJSON()与显式模式和动态语句一起使用。

工作示例:

输入:

CREATE TABLE #Data (
   RowNum int,
   Line nvarchar(max)
)
INSERT INTO #Data
   (RowNum, Line)
VALUES
   (1, 'ColumnA;ColumnB;ColumnC'),
   (2, 'ValueA1;ValueB1;ValueC1'),
   (3, 'ValueA2;ValueB2;ValueC2'),
   (4, 'ValueA3;ValueB3;ValueC3'),
   (5, 'ValueA4;ValueB4;ValueC4'),
   (6, 'ValueA5;ValueB5;ValueC5')

T-SQL:

-- Explicit schema generation
DECLARE @schema nvarchar(max)
SELECT @schema = STUFF((
   SELECT CONCAT(N',', j.[value], N' nvarchar(max) ''$[', j.[key], N']''')
   FROM #Data d
   CROSS APPLY OPENJSON(CONCAT(N'["', REPLACE(d.Line, ';', '","'), N'"]')) j
   WHERE d.RowNum = 1
   FOR XML PATH('')
), 1, 1, N'')

-- Dymanic statement
DECLARE @stm nvarchar(max)
SET @stm = CONCAT(
   N'SELECT j.* FROM #Data d ',
   N'CROSS APPLY OPENJSON(CONCAT(N''[["'', REPLACE(d.Line, '';'', ''","''), N''"]]'')) ',
   N'WITH (',
   @schema,
   N') j WHERE d.RowNum > 1'
)

-- Execution
EXEC sp_executesql @stm

输出:

-----------------------
ColumnA ColumnB ColumnC
-----------------------
ValueA1 ValueB1 ValueC1
ValueA2 ValueB2 ValueC2
ValueA3 ValueB3 ValueC3
ValueA4 ValueB4 ValueC4
ValueA5 ValueB5 ValueC5

说明:

主要部分是将每一行的数据转换为有效的JSON数组。列数可以不同。

第一行中的数据将用于显式模式生成,并将值ColumnA;ColumnB;ColumnC转换为["ColumnA","ColumnB","ColumnC"]。后续行ValueA1;ValueB1;ValueC1中的值将转换为[["ValueA1","ValueB1","ValueC1"]]

接下来的简单示例演示OPENJSON()如何使用默认和显式架构返回数据:

使用默认架构:

DECLARE @json nvarchar(max)
SET @json = '["ValueA1", "ValueB1", "ValueC1"]'
SELECT *
FROM OPENJSON(@json) 

默认模式的输出:

----------------
key value   type
----------------
0   ValueA1 1
1   ValueB1 1
2   ValueC1 1

具有显式架构:

SET @json = '[["ValueA1", "ValueB1", "ValueC1"]]'
SELECT *
FROM OPENJSON(@json) 
WITH (
   ColumnA nvarchar(max) '$[0]',
   ColumnB nvarchar(max) '$[1]',
   ColumnC nvarchar(max) '$[2]'
)

显式模式的输出:

-----------------------
ColumnA ColumnB ColumnC
-----------------------
ValueA1 ValueB1 ValueC1