反透视表数据

Posted

技术标签:

【中文标题】反透视表数据【英文标题】:Unpivot table data 【发布时间】:2014-07-07 12:19:46 【问题描述】:
 Sno    Water   Milk
  1      50     100
  2      22     120
  3      11     142

我有这张桌子。现在我想要类似的结果

  Sno   Type   Qnty
   1    Water   83
   2     Milk   362

我该怎么告诉我。

【问题讨论】:

为什么Sno 1 代表水,2 代表牛奶?这个选择背后有什么逻辑还是只是一个任意的行号? 只是行号 【参考方案1】:

SQL Server 2008 不支持这种语句。

您可以通过两种方式实现:

使用临时表(变量类型表) DECLARE @products TABLE(Sno INT, Water INT, Milk INT)

 INSERT INTO @products
 VALUES (1, 50, 100), (2, 22, 120), (3, 11, 142)


 SELECT ROW_NUMBER() OVER(ORDER BY SUM(Qnty)) AS RowNo, Product, SUM(Qnty) AS Qnty
 FROM (
  SELECT Product, Qnty
 FROM (
    SELECT *
    FROM @products
     ) AS pvt
 UNPIVOT (Qnty FOR Product IN ([Water],[Milk])) AS unpvt
 ) AS T
 GROUP BY Product</pre>

;WITH T AS
 (
 SELECT Sno, Water, Milk
  FROM (
  SELECT 1 AS Sno, 50 AS Water, 100 AS Milk
  UNION ALL
  SELECT 2, 22, 120
  UNION ALL
  SELECT 3, 11, 142
  ) t (Sno, Water, Milk))
   SELECT  Sno = ROW_NUMBER() OVER(ORDER BY SUM(Upvt.Qnty)),
    upvt.Type,
    Qnty = SUM(Upvt.Qnty)
    FROM    T
   UNPIVOT
    (   Qnty
        FOR Type IN ([Water], [Milk])
    ) upvt
   GROUP BY upvt.Type
   ORDER BY Qnty;</pre>

   Please,refer MSDN documentation.

【讨论】:

【参考方案2】:

第一步是UNPIVOT你的数据:

WITH T AS
(   SELECT Sno, Water, Milk
    FROM (VALUES (1, 50, 100), (2, 22, 120), (3, 11, 142)) t (Sno, Water, Milk)
)
SELECT  upvt.Sno,
        upvt.Type,
        Upvt.Qnty
FROM    T
        UNPIVOT
        (   Qnty
            FOR Type IN ([Water], [Milk])
        ) AS upvt;

这将给:

Sno Type    Qnty
1   Water   50
1   Milk    100
2   Water   22
2   Milk    120
3   Water   11
3   Milk    142

然后您可以对该结果应用普通聚合:

WITH T AS
(   SELECT Sno, Water, Milk
    FROM (VALUES (1, 50, 100), (2, 22, 120), (3, 11, 142)) t (Sno, Water, Milk)
)
SELECT  Sno = ROW_NUMBER() OVER(ORDER BY SUM(Upvt.Qnty)),
        upvt.Type,
        Qnty = SUM(Upvt.Qnty)
FROM    T
        UNPIVOT
        (   Qnty
            FOR Type IN ([Water], [Milk])
        ) AS upvt
GROUP BY upvt.Type
ORDER BY Qnty;

给予:

Sno Type    Qnty
1   Water   83
2   Milk    362

编辑

根据您的评论,您使用的是 SQL Server 2005,而不是 2008,如下所示是一个完整的工作示例,将在 2005 上工作:

DECLARE @T TABLE (Sno INT, Water INT, Milk INT);
INSERT @T (Sno, Water, Milk) VALUES (1, 50, 100);
INSERT @T (Sno, Water, Milk) VALUES(2, 22, 120);
INSERT @T (Sno, Water, Milk) VALUES(3, 11, 142);

SELECT  Sno = ROW_NUMBER() OVER(ORDER BY SUM(Upvt.Qnty)),
        upvt.Type,
        Qnty = SUM(Upvt.Qnty)
FROM    @T AS T
        UNPIVOT
        (   Qnty
            FOR Type IN ([Water], [Milk])
        ) AS upvt
GROUP BY upvt.Type
ORDER BY Qnty;

在 2005 年,我用来创建示例数据的表值构造函数导致错误,与取消透视然后对数据求和的实际查询无关。

【讨论】:

它给出了这样的错误“关键字'VALUES'附近的语法不正确。” 您使用的是 SQL Server 2005 吗? 那么你所做的与我发布的内容不同。它在我的 SQL Server 2008 版本和 SQL Fiddle 上运行良好 运行SELECT @@VERSION会得到什么结果? Microsoft SQL Server 2005 - 9.00.1399.06(Intel X86)2005 年 10 月 14 日 00:33:37 版权所有 (c) 1988-2005 Microsoft Corporation Enterprise Edition on Windows NT 5.2(Build 3790:Service Pack 2 )【参考方案3】:

这给出了您要求的结果,但我知道您想要更高级的东西。如果有,请详细说明。

SELECT 'water', sum(water) FROM table_name
UNION ALL 
SELECT 'milk', sum(milk) FROM  table_name

【讨论】:

以上是关于反透视表数据的主要内容,如果未能解决你的问题,请参考以下文章

sql server 反透视表

数据透视/反透视计数

PostgreSQL 中的反透视表

将行反透视成列

反透视表 SQL Oracle

SQL 从反透视表中删除过滤器