是否可以使用 SQL Server 使用相同的数据透视列进行多个数据透视
Posted
技术标签:
【中文标题】是否可以使用 SQL Server 使用相同的数据透视列进行多个数据透视【英文标题】:Is it possible to have multiple pivots using the same pivot column using SQL Server 【发布时间】:2013-02-22 20:02:43 【问题描述】:我正面临以下挑战。我需要在同一列上旋转表数据两次。 这是数据的截图。
我想为每个项目 ID 设置一行,其中包含每年的购买价值和销售价值。 我尝试通过选择“年份”列两次,对其进行格式化,以便每个销售年份以“S”为前缀,每个采购年份以“P”开头,并使用 2 个枢轴围绕 2 年列旋转.这是 SQL 查询(用于 SQL Server 2008):
SELECT [Item ID],
[P2000],[P2001],[P2002],[P2003],
[S2000],[S2001],[S2002],[S2003]
FROM
(
SELECT [Item ID]
,'P' + [Year] AS YearOfPurchase
,'S' + [Year] AS YearOfSelling
,[Purchasing value]
,[Selling value]
FROM [ItemPrices]
) AS ALIAS
PIVOT
(
MIN ([Purchasing value]) FOR [YearOfPurchase] in ([P2000],[P2001],[P2002],[P2003])
)
AS pvt
PIVOT
(
MIN ([Selling value]) FOR [YearOfSelling] in ([S2000],[S2001],[S2002],[S2003])
)
AS pvt2
结果并不是我所希望的(见下图):
如您所见,每个项目 ID 仍然不止一行。有没有办法将行数减少到每个项目正好一个?这样看起来有点像下面的 Excel 截图?
【问题讨论】:
正是我需要的问题——我自己会问类似的问题! 【参考方案1】:我的建议是同时应用 UNPIVOT
和 PIVOT
函数来获得结果。
UNPIVOT
会将PurchasingValue
和SellingValue
列转换为行。完成此操作后,您可以将数据转换为结果。
代码将是:
select *
from
(
select itemid,
case
when col = 'PurchasingValue' then 'P'
when col = 'SellingValue' then 'S'
end + cast(year as varchar(4)) new_col,
value
from yourtable
unpivot
(
value
for col in ([PurchasingValue], [SellingValue])
) unpiv
) src
pivot
(
max(value)
for new_col in (P2000, P2001, P2002, P2003,
S2000, S2001, S2002, S2003)
) piv;
见SQL Fiddle with Demo。结果是:
| ITEMID | P2000 | P2001 | P2002 | P2003 | S2000 | S2001 | S2002 | S2003 |
--------------------------------------------------------------------------
| 1 | 1000 | 1100 | 1200 | 1300 | 900 | 990 | 1080 | 1170 |
| 2 | 500 | 550 | 600 | 650 | 450 | 495 | 540 | 585 |
在 SQL Server 2008+ 中,您可以使用 CROSS APPLY
和 VALUES
以及 PIVOT
函数:
select *
from
(
select itemid,
col+cast(year as varchar(4)) new_col,
value
from yourtable
cross apply
(
VALUES
(PurchasingValue, 'P'),
(SellingValue, 'S')
) x (value, col)
) src
pivot
(
max(value)
for new_col in (P2000, P2001, P2002, P2003,
S2000, S2001, S2002, S2003)
) piv
见SQL Fiddle with Demo
【讨论】:
感谢 unpivot 建议。我没有想到这一点(并且不确定将来是否会这样:-)) @RobVermeulen 是的,unpivot 函数效果很好。我刚刚用一个也使用cross apply
的版本更新了我的答案。两者都会得到相同的结果。
@RobVermeulen 这很难说,这真的取决于很多因素。如果您担心速度,则应尝试查询的不同变体,以确定最适合您的情况。
我知道谢谢你的帖子不受欢迎,但我只想告诉你非常感谢!先生,你救了我的一周。在到达这篇文章之前,我发现的唯一解决方案是在同一张表上旋转两次,然后加入它们,但由于某种原因,第二个枢轴在连接的笛卡尔积上运行,而不是在表本身上运行,所以只要行数超过1000,执行时间飞涨。所以只有在知道 unpivot 的存在(感谢你)之后,我才能解决我的问题。干杯!
@Alain 如果您使用 CROSS APPLY 版本,那么您可以将值转换/转换为相同的数据类型。【参考方案2】:
透视多个列的一种简单方法是仅使用 Aggregate(Case) 表达式。
SELECT [Item ID],
[P2000] = SUM(CASE WHEN [Year] = 2000 THEN [Purchasing value] END),
[P2001] = SUM(CASE WHEN [Year] = 2001 THEN [Purchasing value] END),
[P2002] = SUM(CASE WHEN [Year] = 2002 THEN [Purchasing value] END),
[P2003] = SUM(CASE WHEN [Year] = 2003 THEN [Purchasing value] END),
[S2000] = SUM(CASE WHEN [Year] = 2000 THEN [Selling value] END),
[S2001] = SUM(CASE WHEN [Year] = 2001 THEN [Selling value] END),
[S2002] = SUM(CASE WHEN [Year] = 2002 THEN [Selling value] END),
[S2003] = SUM(CASE WHEN [Year] = 2003 THEN [Selling value] END)
FROM ItemPrices
GROUP BY [Item ID]
【讨论】:
【参考方案3】:使用 GROUP BY ItemID,并在每个结果列上使用聚合函数 SUM(isnull(value,0))。
【讨论】:
以上是关于是否可以使用 SQL Server 使用相同的数据透视列进行多个数据透视的主要内容,如果未能解决你的问题,请参考以下文章
雪花是不是支持 sql server 中使用的几何数据类型?
是否可以同时更新 SQL Server 数据库和 Informix 数据库?
是否可以使用 Pymssql 通过域(Windows)用户帐户远程访问 SQL Server 2012