2

使用此表:

| 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小提琴

4

2 回答 2

3

真的,您想要UNPIVOT处理多个列,然后PIVOT获取您的数据。我最喜欢的做法UNPIVOT是使用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
于 2013-07-18T16:12:31.860 回答
1

你可以用CROSS-APPLYand做到这一点PIVOT

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 小提琴

于 2013-07-18T15:36:15.817 回答