是否可以使用SQL Server使用相同的枢轴列具有多个枢轴

Rob*_*len 14 sql sql-server pivot unpivot

我正面临着以下挑战.我需要在同一列上旋转两次表数据.这是数据的屏幕截图.

每件商品的购买和销售价值列表

我希望每个商品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
Run Code Online (Sandbox Code Playgroud)

结果并不完全是我所希望的(见下图):

实际情况:行太多

如您所见,每个商品ID仍有多行.有没有办法将每行的行数减少到一个?所以它看起来有点像下面的Excel截图?

所需情况:每个商品ID一行

Tar*_*ryn 23

我的建议是应用UNPIVOTPIVOT函数来获得结果.

UNPIVOT会变成PurchasingValueSellingValue列转换为行.完成此操作后,您可以将数据转移到结果中.

代码将是:

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;
Run Code Online (Sandbox Code Playgroud)

请参阅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 |
Run Code Online (Sandbox Code Playgroud)

在SQL Server 2008+可以使用CROSS APPLYVALUES与沿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
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo


Jam*_*D77 8

枢转多个列的一种简单方法是仅使用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]
Run Code Online (Sandbox Code Playgroud)


Pie*_*ens 5

使用 GROUP BY ItemID,并在每个结果列上使用聚合函数 SUM(isnull(value,0))。