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)

如果你这样做,它会给你想要的结果