SQL 将行中的不同项目转换为列
SQL to convert distinct item in row to column
我有一个 table 作为
Date Item Quantity
20170101 Mango 5
20170101 Orange 6
20170102 Mango 7
20170102 Orange 8
我想要下面的输出
Date Mango Orange
20170101 5 6
20170102 7 8
为此我在下面使用了 sql 查询
SELECT
Date,
SUM(case when Item='Mango' then Quantity else 0 end) AS Mango,
SUM(case when Item='Orange' then Quantity else 0 end) AS Orange
FROM orderTable
GROUP BY date
但这是一种针对 Mango 和 Orange 的硬编码。如果我需要 orderTable 中的新项目怎么办?谁能建议我如何使此查询动态化。因此,如果我添加新项目,它会自动创建新的 coulmn,并将项目名称作为名称,并且当未为该项目下订单时,它在日期列下的值为 0。
喜欢
Date Item Quantity
20170101 Mango 5
20170101 Orange 6
20170102 Mango 7
20170102 Orange 8
20170102 Cherry 9
那么输出应该是...
Date Mango Orange Cherry
20170101 5 6 0
20170102 7 8 9
IF OBJECT_ID('Tempdb..#Temp') IS NOt NUll
Drop Table #Temp
;With cte([Date] ,Item ,Quantity)
AS
(
SELECT '20170101','Mango' ,5 Union all
SELECT '20170101','Orange' ,6 Union all
SELECT '20170102','Mango' ,7 Union all
SELECT '20170102','Orange' ,8 Union all
SELECT '20170102','Cherry' ,9
)
SELECT * INTO #Temp FROM cte
DECLARE @dynamicCol nvarchar(max),
@Sql nvarchar(max),
@dynamicCol2 nvarchar(max)
SELECT @dynamicCol=STUFF((SELECT DISTINCT ', ' + 'ISNULL('+Item +',''0'') AS '+ Item FROM #Temp
FOR XML PATH('')),1,1,'')
SELECT @dynamicCol2=STUFF((SELECT DISTINCT ', ' + Item FROM #Temp
FOR XML PATH('')),1,1,'')
SET @Sql='
SELECT [Date] , '+ @dynamicCol +' From
(
SELECT [Date] ,Item ,Quantity From
#temp
)AS Src
PIVOT
(
MAX([Quantity]) For [Item ] IN ('+@dynamicCol2+')
)
AS Pvt
'
PRINT @Sql
EXEC(@Sql)
输出
Date Cherry Mango Orange
----------------------------------
20170101 0 5 6
20170102 9 7 8
IF OBJECT_ID('Test') IS NOt NUll
DROP TABLE Test
CREATE TABLE Test
(
Date VARCHAR(100),
Item VARCHAR(100),
Quantity INT
)
INSERT Test VALUES
('20170101', 'Mango', 5),
('20170101', 'Orange', 6),
('20170102', 'Mango', 7),
('20170102', 'Orange', 8),
('20170102', 'Cherry', 9)
DECLARE @SQL AS VARCHAR(MAX)
DECLARE @Columns AS VARCHAR(MAX)
DECLARE @Columns2 AS VARCHAR(MAX)
SELECT @Columns = COALESCE(@Columns + ',','') + QUOTENAME(Item)
FROM (SELECT DISTINCT Item FROM Test) AS B
ORDER BY B.Item
SELECT @Columns2 = COALESCE(@Columns2 + ',','') + 'ISNULL(' + QUOTENAME(Item) + ', 0) AS ' + Item
FROM (SELECT DISTINCT Item FROM Test) AS B
ORDER BY B.Item
SET @SQL = '
WITH PivotData AS
(
SELECT Date, Item, Quantity FROM Test
)
SELECT
Date, ' + @Columns2 + '
FROM PivotData
PIVOT
(
SUM(Quantity)
FOR Item
IN (' + @Columns + ')
) AS PivotResult
ORDER BY Date'
EXEC(@SQL);
DROP TABLE Test
结果:
Date Cherry Mango Orange
20170101 0 5 6
20170102 9 7 8
参考(代码图片未显示,但如果您查看页面源代码,您可以访问它):
http://sqlmag.com/t-sql/pivoting-dynamic-way
试试这个:
CREATE TABLE [dbo].[test](
[Date] [int] NULL,
[Item] [nvarchar](50) NULL,
[Quantity] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170101, N'Mango', 5)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170101, N'Orange', 6)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Mango', 7)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Orange', 8)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Cherry', 5)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170103, N'Cherry', 2)
GO
动态 sql :
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(Item)
from test
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT DATE, ' + @cols + N' from
(
select Date,Item, Quantity from test
) x
pivot
(
max(Quantity)
for Item in (' + @cols + N')
) p '
exec sp_executesql @query;
结果:
DATE Cherry Mango Orange
20170101 NULL 5 6
20170102 5 7 8
20170103 2 NULL NULL
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Item)
FROM dbo.OrderTable c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT DateOrdered, ' + @cols + ' from
(
select Item, DateOrdered, Quantity
from dbo.OrderTable
) x
pivot
(
Sum(Quantity)
for Item in (' + @cols + ')
) p '
execute(@query)
如果你这样做,它会给你想要的结果
我有一个 table 作为
Date Item Quantity
20170101 Mango 5
20170101 Orange 6
20170102 Mango 7
20170102 Orange 8
我想要下面的输出
Date Mango Orange
20170101 5 6
20170102 7 8
为此我在下面使用了 sql 查询
SELECT
Date,
SUM(case when Item='Mango' then Quantity else 0 end) AS Mango,
SUM(case when Item='Orange' then Quantity else 0 end) AS Orange
FROM orderTable
GROUP BY date
但这是一种针对 Mango 和 Orange 的硬编码。如果我需要 orderTable 中的新项目怎么办?谁能建议我如何使此查询动态化。因此,如果我添加新项目,它会自动创建新的 coulmn,并将项目名称作为名称,并且当未为该项目下订单时,它在日期列下的值为 0。
喜欢
Date Item Quantity
20170101 Mango 5
20170101 Orange 6
20170102 Mango 7
20170102 Orange 8
20170102 Cherry 9
那么输出应该是...
Date Mango Orange Cherry
20170101 5 6 0
20170102 7 8 9
IF OBJECT_ID('Tempdb..#Temp') IS NOt NUll
Drop Table #Temp
;With cte([Date] ,Item ,Quantity)
AS
(
SELECT '20170101','Mango' ,5 Union all
SELECT '20170101','Orange' ,6 Union all
SELECT '20170102','Mango' ,7 Union all
SELECT '20170102','Orange' ,8 Union all
SELECT '20170102','Cherry' ,9
)
SELECT * INTO #Temp FROM cte
DECLARE @dynamicCol nvarchar(max),
@Sql nvarchar(max),
@dynamicCol2 nvarchar(max)
SELECT @dynamicCol=STUFF((SELECT DISTINCT ', ' + 'ISNULL('+Item +',''0'') AS '+ Item FROM #Temp
FOR XML PATH('')),1,1,'')
SELECT @dynamicCol2=STUFF((SELECT DISTINCT ', ' + Item FROM #Temp
FOR XML PATH('')),1,1,'')
SET @Sql='
SELECT [Date] , '+ @dynamicCol +' From
(
SELECT [Date] ,Item ,Quantity From
#temp
)AS Src
PIVOT
(
MAX([Quantity]) For [Item ] IN ('+@dynamicCol2+')
)
AS Pvt
'
PRINT @Sql
EXEC(@Sql)
输出
Date Cherry Mango Orange
----------------------------------
20170101 0 5 6
20170102 9 7 8
IF OBJECT_ID('Test') IS NOt NUll
DROP TABLE Test
CREATE TABLE Test
(
Date VARCHAR(100),
Item VARCHAR(100),
Quantity INT
)
INSERT Test VALUES
('20170101', 'Mango', 5),
('20170101', 'Orange', 6),
('20170102', 'Mango', 7),
('20170102', 'Orange', 8),
('20170102', 'Cherry', 9)
DECLARE @SQL AS VARCHAR(MAX)
DECLARE @Columns AS VARCHAR(MAX)
DECLARE @Columns2 AS VARCHAR(MAX)
SELECT @Columns = COALESCE(@Columns + ',','') + QUOTENAME(Item)
FROM (SELECT DISTINCT Item FROM Test) AS B
ORDER BY B.Item
SELECT @Columns2 = COALESCE(@Columns2 + ',','') + 'ISNULL(' + QUOTENAME(Item) + ', 0) AS ' + Item
FROM (SELECT DISTINCT Item FROM Test) AS B
ORDER BY B.Item
SET @SQL = '
WITH PivotData AS
(
SELECT Date, Item, Quantity FROM Test
)
SELECT
Date, ' + @Columns2 + '
FROM PivotData
PIVOT
(
SUM(Quantity)
FOR Item
IN (' + @Columns + ')
) AS PivotResult
ORDER BY Date'
EXEC(@SQL);
DROP TABLE Test
结果:
Date Cherry Mango Orange
20170101 0 5 6
20170102 9 7 8
参考(代码图片未显示,但如果您查看页面源代码,您可以访问它): http://sqlmag.com/t-sql/pivoting-dynamic-way
试试这个:
CREATE TABLE [dbo].[test](
[Date] [int] NULL,
[Item] [nvarchar](50) NULL,
[Quantity] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170101, N'Mango', 5)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170101, N'Orange', 6)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Mango', 7)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Orange', 8)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170102, N'Cherry', 5)
GO
INSERT [dbo].[test] ([Date], [Item], [Quantity]) VALUES (20170103, N'Cherry', 2)
GO
动态 sql :
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(Item)
from test
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT DATE, ' + @cols + N' from
(
select Date,Item, Quantity from test
) x
pivot
(
max(Quantity)
for Item in (' + @cols + N')
) p '
exec sp_executesql @query;
结果:
DATE Cherry Mango Orange
20170101 NULL 5 6
20170102 5 7 8
20170103 2 NULL NULL
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Item)
FROM dbo.OrderTable c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT DateOrdered, ' + @cols + ' from
(
select Item, DateOrdered, Quantity
from dbo.OrderTable
) x
pivot
(
Sum(Quantity)
for Item in (' + @cols + ')
) p '
execute(@query)
如果你这样做,它会给你想要的结果