SQL 使用列名转置数据
SQL Transpose Data with Column Name
我正在尝试将 SQL 服务器 table 中的数据转置为一行数据但有几列数据,所有数据连同它们各自的列 headers。
原始数据Table:
**TABLE Column Names:** Id, ColumnA , ColumnB , ColumnC , StartDate
**Data:** 1, 'aa' , 'bb' , 'cc', 2016-10-10
要求的数据格式:
**ColumnName Values**
Id 1
ColumnA aa
ColumnB bb
ColumnC cc
StartDate 2016-10-10
CREATE DATABASE ToDelete
GO
USE [ToDelete]
GO
CREATE TABLE [dbo].[sourceData](
[id] [int] NULL,
[ColumnA] [varchar](50) NULL,
[ColumnB] [varchar](50) NULL,
[ColumnC] [varchar](50) NULL,
[StartDate] [datetime] NULL
)
GO
INSERT [dbo].[sourceData] ([id], [ColumnA], [ColumnB], [ColumnC], [StartDate], [EndDate]) VALUES (1, 'aa', N'bb', N'cc', GETDATE())
GO
我用来提取 table 列名称的查询是:
SELECT c.name
FROM sys.tables t
JOIN sys.columns c
ON t.object_id = c.object_id
WHERE t.name = 'sourceData'
我们将不胜感激。
谢谢
这里有一个选项可以帮助您创建更像 EAV 结构的东西
例子
Declare @YourTable Table ([Id] varchar(50),[ColumnA] varchar(50),[ColumnB] varchar(50),[ColumnC] varchar(50),[StartDate] date)
Insert Into @YourTable Values
(1,'aa','bb','cc','2016-10-10')
Select A.ID
,C.*
From @YourTable A
Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
Cross Apply (
Select Field = a.value('local-name(.)','varchar(100)')
,Value = a.value('.','varchar(max)')
From B.XMLData.nodes('/row') as C1(n)
Cross Apply C1.n.nodes('./@*') as C2(a)
Where a.value('local-name(.)','varchar(100)') not in ('ID','OtherColumnsTo','Exclude')
) C
Returns
ID Field Value
1 ColumnA aa
1 ColumnB bb
1 ColumnC cc
1 StartDate 2016-10-10
只需像这样使用Union all
:
select Id,'ColumnA' columnName, ColumnA [Values]
from t
union all
select Id,'ColumnB' , ColumnB
from t
union all
select Id,'ColumnC' , ColumnC
from t
union all
select Id,'StartDate' , cast(StartDate as nvarchar(max))
from t;
尝试以下解决方案,我参考了以下文章来编写此查询:
https://www.red-gate.com/simple-talk/sql/t-sql-programming/questions-about-pivoting-data-in-sql-server-you-were-too-shy-to-ask/
USE [ToDelete]
GO
DECLARE @sql AS NVARCHAR(2000);DECLARE @col AS NVARCHAR(2000);
DECLARE @col1 AS NVARCHAR(2000);
SELECT @col = ISNULL(@col + ', ', '') +
concat('cast(',QUOTENAME(column_name),'as nvarchar(max))',' ',
QUOTENAME(column_name) ),@col1=ISNULL(@col1 + ', ', '') +QUOTENAME(column_name)
FROM (SELECT DISTINCT column_name FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='sourceData') AS Colname;
SET @sql =N'select columnname,[values] from (select '+@col+ ' from dbo.sourceData) as D Unpivot
([values] for columnname in (' + @col1 + '))
as unpiv'
EXEC sp_executesql @sql;
使用 unpivot
的其他变体:
数据集
DECLARE @YourTable TABLE
([Id] VARCHAR(10),
[ColumnA] VARCHAR(10),
[ColumnB] VARCHAR(10),
[ColumnC] VARCHAR(10),
[StartDate] DATE
);
INSERT INTO @YourTable
VALUES
(1, 'aa', 'bb', 'cc', '2016-10-10'),
(2, 'cc', 'dd', 'zz', '2016-10-11');
查询
SELECT Id,
Field,
[Value]
FROM
( SELECT Id,
ColumnA,
ColumnB,
ColumnC,
CONVERT(VARCHAR(10), StartDate) AS StartDate
FROM @YourTable
) AS t UNPIVOT([Value] FOR [Field] IN ( ColumnA,
ColumnB,
ColumnC,
StartDate)) up;
我正在尝试将 SQL 服务器 table 中的数据转置为一行数据但有几列数据,所有数据连同它们各自的列 headers。
原始数据Table:
**TABLE Column Names:** Id, ColumnA , ColumnB , ColumnC , StartDate
**Data:** 1, 'aa' , 'bb' , 'cc', 2016-10-10
要求的数据格式:
**ColumnName Values**
Id 1
ColumnA aa
ColumnB bb
ColumnC cc
StartDate 2016-10-10
CREATE DATABASE ToDelete
GO
USE [ToDelete]
GO
CREATE TABLE [dbo].[sourceData](
[id] [int] NULL,
[ColumnA] [varchar](50) NULL,
[ColumnB] [varchar](50) NULL,
[ColumnC] [varchar](50) NULL,
[StartDate] [datetime] NULL
)
GO
INSERT [dbo].[sourceData] ([id], [ColumnA], [ColumnB], [ColumnC], [StartDate], [EndDate]) VALUES (1, 'aa', N'bb', N'cc', GETDATE())
GO
我用来提取 table 列名称的查询是:
SELECT c.name
FROM sys.tables t
JOIN sys.columns c
ON t.object_id = c.object_id
WHERE t.name = 'sourceData'
我们将不胜感激。
谢谢
这里有一个选项可以帮助您创建更像 EAV 结构的东西
例子
Declare @YourTable Table ([Id] varchar(50),[ColumnA] varchar(50),[ColumnB] varchar(50),[ColumnC] varchar(50),[StartDate] date)
Insert Into @YourTable Values
(1,'aa','bb','cc','2016-10-10')
Select A.ID
,C.*
From @YourTable A
Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
Cross Apply (
Select Field = a.value('local-name(.)','varchar(100)')
,Value = a.value('.','varchar(max)')
From B.XMLData.nodes('/row') as C1(n)
Cross Apply C1.n.nodes('./@*') as C2(a)
Where a.value('local-name(.)','varchar(100)') not in ('ID','OtherColumnsTo','Exclude')
) C
Returns
ID Field Value
1 ColumnA aa
1 ColumnB bb
1 ColumnC cc
1 StartDate 2016-10-10
只需像这样使用Union all
:
select Id,'ColumnA' columnName, ColumnA [Values]
from t
union all
select Id,'ColumnB' , ColumnB
from t
union all
select Id,'ColumnC' , ColumnC
from t
union all
select Id,'StartDate' , cast(StartDate as nvarchar(max))
from t;
尝试以下解决方案,我参考了以下文章来编写此查询: https://www.red-gate.com/simple-talk/sql/t-sql-programming/questions-about-pivoting-data-in-sql-server-you-were-too-shy-to-ask/
USE [ToDelete]
GO
DECLARE @sql AS NVARCHAR(2000);DECLARE @col AS NVARCHAR(2000);
DECLARE @col1 AS NVARCHAR(2000);
SELECT @col = ISNULL(@col + ', ', '') +
concat('cast(',QUOTENAME(column_name),'as nvarchar(max))',' ',
QUOTENAME(column_name) ),@col1=ISNULL(@col1 + ', ', '') +QUOTENAME(column_name)
FROM (SELECT DISTINCT column_name FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='sourceData') AS Colname;
SET @sql =N'select columnname,[values] from (select '+@col+ ' from dbo.sourceData) as D Unpivot
([values] for columnname in (' + @col1 + '))
as unpiv'
EXEC sp_executesql @sql;
使用 unpivot
的其他变体:
数据集
DECLARE @YourTable TABLE
([Id] VARCHAR(10),
[ColumnA] VARCHAR(10),
[ColumnB] VARCHAR(10),
[ColumnC] VARCHAR(10),
[StartDate] DATE
);
INSERT INTO @YourTable
VALUES
(1, 'aa', 'bb', 'cc', '2016-10-10'),
(2, 'cc', 'dd', 'zz', '2016-10-11');
查询
SELECT Id,
Field,
[Value]
FROM
( SELECT Id,
ColumnA,
ColumnB,
ColumnC,
CONVERT(VARCHAR(10), StartDate) AS StartDate
FROM @YourTable
) AS t UNPIVOT([Value] FOR [Field] IN ( ColumnA,
ColumnB,
ColumnC,
StartDate)) up;