在SQL上使用Group by Pivot

时间:2016-11-09 02:21:56

标签: sql-server

我创建了sql语法,根据类别

创建了按产品分组的数据透视表
CREATE TABLE #Product ( Product varchar(10),Category varchar(10),Stock int)

INSERT INTO #Product Values ('Item A','CatA',10)

INSERT INTO #Product Values ('Item A','CatB',5)

INSERT INTO #Product Values ('Item B','CatA',3)

INSERT INTO #Product Values ('Item B','CatB',5)

INSERT INTO #Product Values ('Item B','CatC',7)
INSERT INTO #Product Values ('Item B','CatD',10)

SELECT * 
FROM 
(
  SELECT Product,Category,Stock
  FROM #Product A

) src
pivot
(
  SUM(Stock)
  for Category in ([CatA], [CatB], [CatC],[CatD])
) piv;

DROP TABLE #Product

查询结果

 Product    CatA    CatB    CatC    CatD
 Item A      10      5      NULL     NULL
 Item B      3       5       7       10

尝试实现的结果是

 Product    Cat1 Stock1 Cat2 Stock2 Cat3 Stock3 Cat4   Stock4   
 Item A     CatA    10  CatB  5     CatC    0   CatD     0
 Item B     CatA    3   CatB  5     CatC    7   CatD     10

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

您需要先创建ProductCategory的所有组合。然后在LEFT JOIN上执行#Product以获取Stock。最后,使用结果来转动数据。

由于我不熟悉PIVOT命令,我使用了另一种名为Dynamic Crosstab的技术

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql = 
'SELECT
    Product' + CHAR(10);

SELECT @sql = @sql +
STUFF((
    SELECT 
        '   ,MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), t.RN) + ' THEN Category END) AS ' + QUOTENAME('Cat' + CONVERT(VARCHAR(3), t.RN)) + CHAR(10) +
        '   ,MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), t.RN) + ' THEN Stock END) AS ' + QUOTENAME('Stock' + CONVERT(VARCHAR(3), t.RN)) + CHAR(10)
    FROM (
        SELECT DISTINCT 
            RN = ROW_NUMBER() OVER(PARTITION BY Product ORDER BY(SELECT NULL))
        FROM #Product
    ) t
    FOR XML PATH('')
), 1, 1, '  ');

SELECT @sql = @sql +
'FROM(
    SELECT
        p1.Product,
        p1.Category,
        Stock = ISNULL(p2.Stock, 0),
        RN = ROW_NUMBER() OVER(PARTITION BY p1.Product ORDER BY p1.Category)
    FROM (
        SELECT
            t1.Product, t2.Category
        FROM (
            SELECT DISTINCT Product FROM #Product
        ) t1
        CROSS JOIN (
            SELECT DISTINCT Category FROM #Product
        ) t2
    ) p1
    LEFT JOIN #Product p2
        ON p1.Product = p2.Product
        AND p1.Category = p2.Category
)t
GROUP BY Product;';

PRINT @sql;
EXEC sp_executesql @sql;

ONLINE DEMO