SQL Server:如何在新列具有多个唯一值的位置进行透视

时间:2013-07-18 15:15:50

标签: sql sql-server pivot

使用此表:

| CUST | PRODUCT | QTY | SMALLEST |
-----------------------------------
|    E |    1600 |   2 |        1 |
|    F |    1600 |   6 |        9 |
|    G |    1600 |   1 |        8 |

我想将它转动为使它看起来像这样:

|    E    |    F    |   G    |
------------------------------
|    1600 |    1600 |   1600 |
|    2    |    6    |   1    |
|    1    |    9    |   8    |

我通过一个独特的行来了解如何做到这一点。如果我只有QTY或只有SMALLEST,它可以正常使用此查询,例如:

查询

SELECT E, F, G
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (E,F,G)) AS pvt

输出

| E | F | G |
-------------
| 2 | 6 | 1 |

但是,如果我在另一个查询的混合中添加另一列,我就会搞得一团糟:

查询

SELECT E, F, G
FROM (
SELECT CUST, PRODUCT, QTY, SMALLEST
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (E,F,G)) AS pvt

输出

|      E |      F |      G |
----------------------------
|      2 | (null) | (null) |
| (null) | (null) |      1 |
| (null) |      6 | (null) |

当我更改查询时,很容易理解为什么:

查询

SELECT product,smallest, E, F, G
FROM (
SELECT CUST, PRODUCT, QTY, SMALLEST
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (E,F,G)) AS pvt

输出

| PRODUCT | SMALLEST |      E |      F |      G |
-------------------------------------------------
|    1600 |        1 |      2 | (null) | (null) |
|    1600 |        8 | (null) | (null) |      1 |
|    1600 |        9 | (null) |      6 | (null) |

模式变得明显。它发现有1600和1有一个E值:2,有1600和8有一个F值6,等等。

我遇到了问题,但我不知道如何修复它。有人可以帮我完成我徒劳的任务吗?

SQL Fiddle

2 个答案:

答案 0 :(得分:3)

您真的希望UNPIVOT处理多个列,然后PIVOT来获取您的数据。我最喜欢做UNPIVOT is to use CROSS APPLY的方式,但是你可以随心所欲地做到这一点。像这样。

SELECT E, F, G
FROM (
SELECT CUST, ColumnName, Value
FROM Product
CROSS APPLY ( VALUES ('PRODUCT', PRODUCT),
                        ('QTY', QTY),
                        ('SMALLEST',SMALLEST)) 
    UnPivoted(ColumnName, Value)) up
PIVOT (SUM(VALUE) FOR CUST IN (E,F,G)) AS pvt

当然,如果您想查看值来自哪个列:

SELECT ColumnName, E, F, G
FROM (
SELECT CUST, ColumnName, Value
FROM Product
CROSS APPLY ( VALUES ('PRODUCT', PRODUCT),
                        ('QTY', QTY),
                        ('SMALLEST',SMALLEST)) 
    UnPivoted(ColumnName, Value)) up
PIVOT (SUM(VALUE) FOR CUST IN (E,F,G)) AS pvt

编辑:

这是多种类型的解决方案。基本上你必须做多个查询,每个数据类型一个。除此之外,您的数字查询中有一个SUM,它不适用于varchar列。您的输出也必须完全相同。这意味着您必须将任何数字或日期列转换为varchar。

SELECT ColumnName, CAST(E AS varchar(30)) E, CAST(F AS varchar(30)) F, CAST(G AS varchar(30)) G
FROM (
SELECT CUST, ColumnName, Value
FROM Product
CROSS APPLY ( VALUES ('PRODUCT', PRODUCT),
                        ('QTY', QTY),
                        ('SMALLEST',SMALLEST)) 
    UnPivoted(ColumnName, Value)) up
PIVOT (SUM(VALUE) FOR CUST IN (E,F,G)) AS pvt
UNION ALL
SELECT ColumnName, E, F, G
FROM (
SELECT CUST, ColumnName, Value
FROM Product
CROSS APPLY ( VALUES ('CharColA', CharColA),
                        ('CharColB', CharColB)) 
    UnPivoted(ColumnName, Value)) up
PIVOT (MIN(VALUE) FOR CUST IN (E,F,G)) AS pvt

答案 1 :(得分:1)

您可以使用CROSS-APPLYPIVOT

执行此操作
SELECT E,F,G
FROM
(
  SELECT Cust,col,value
  FROM #Product
  CROSS APPLY
  (
    VALUES ('E', Product),('F', QTY),('G', SMALLEST)
  ) C (COL, VALUE)
) SRC
PIVOT
(
  MAX(VALUE)
  FOR CUST IN (E,F,G)
) PIV

演示:SQL Fiddle