我有两个数据表
表1
---------------------------------------------------
| SALEID | SOLDBY | SALEPRICE | MARGIN | DATE |
| 1 | 'aa' | 10,000 | 10 | 2013-1-1 |
| 2 | 'bb' | 25,000 | 5 | 2013-5-1 |
表2
---------------------------------------------------
| SALEITEMID | SALEID | SALEPRICE | CATEGORY |
| 1 | 1 | 6,000 | BOOKS |
| 2 | 1 | 4,000 | PRINTING |
| 3 | 2 | 5,000 | BOOKS |
| 4 | 2 | 12,000 | PRINTING |
| 5 | 2 | 8,000 | DVD |
我需要一个会产生
的查询TAB3
--------------------------------------------------------------------------------
| SALEID | SOLDBY | SALEPRICE | MARGIN | DATE | BOOKS | PRINTING | DVD
| 1 | 'aa' | 10,000 | 10 | 2013-1-1 | 6,000 | 4,000 | 0
| 2 | 'bb' | 25,000 | 5 | 2013-5-1 | 5,000 | 12,000 | 8,000
我对转动非常不熟悉,也不确定是否可以使用转轴。
答案 0 :(得分:43)
这应该有效:
WITH Sales AS (
SELECT
S.SaleID,
S.SoldBy,
S.SalePrice,
S.Margin,
S.Date,
I.SalePrice,
I.Category
FROM
dbo.Sale S
INNER JOIN dbo.SaleItem I
ON S.SaleID = I.SaleID
)
SELECT *
FROM
Sales
PIVOT (Max(SalePrice) FOR Category IN (Books, Printing, DVD)) P
;
或者替代:
SELECT
S.SaleID,
S.SoldBy,
S.SalePrice,
S.Margin,
S.Date,
I.Books,
I.Printing,
I.DVD
FROM
dbo.Sale S
INNER JOIN (
SELECT *
FROM
(SELECT SaleID, SalePrice, Category FROM dbo.SaleItem) I
PIVOT (Max(SalePrice) FOR Category IN (Books, Printing, DVD)) P
) I ON S.SaleID = I.SaleID
;
这些结果集具有相同的结果集,实际上查询优化器可能会对它们进行相同的处理,但可能不会。当您开始在Sale
表上添加条件时,最大的区别就在于它 - 您应该测试并查看哪个查询更好。
但是,我建议您在表示层中进行旋转吗?例如,如果您使用的是SSRS,则很容易使用矩阵控件来完成所有的旋转。这是最好的,因为如果你添加一个新的Category
,你将不会修改所有的SQL代码!
有一种方法可以动态查找要转移的列名,但它涉及动态SQL。我不建议这是最好的方式,尽管它是可能的。
可以工作的另一种方式是预处理此查询 - 意味着在Category
表上设置一个触发器,该触发器重写视图以包含所有现存的类别。这确实解决了我提到的很多其他问题,但同样,使用表示层是最好的。
注意:如果您的列名称(以前是值)包含空格,数字或以数字开头,或者是无效的标识符,则必须使用方括号引用它们,如{ {1}}。或者,您可以在它们到达查询的PIVOT (Max(Value) FOR CategoryId IN ([1], [2], [3], [4])) P
部分之前修改这些值以预先添加一些字母或删除空格,以便列列表不需要转义。有关此内容的进一步阅读,请查看SQL Server中标识符的规则。