【问题标题】:SQL Server 2008 R2 Pivot issueSQL Server 2008 R2 数据透视问题
【发布时间】:2013-05-29 09:30:35
【问题描述】:

我有一个Table1 显示在这里:

;WITH Table1 AS (
SELECT *
FROM (VALUES 
(164021, 'Balajee', 100, 100, 'YTD'),
(164021, 'Balajee', 200, 100, 'YTD'),
(164021, 'Balajee', 400, 300, 'MTD'),
(164021, 'Balajee', 200, 100, 'MTD')
) as t (EmpID, [Emp Name], GROSS_PAY, NET_PAY, DUR_TYPE)
)

此表有名为持续时间类型的列,其值为YTDMTD。现在我希望我的表在使用 Pivot 进行选择后看起来如下表所示。有人可以帮我做到这一点吗?我对这个 Pivot 很陌生,需要一些帮助。

EmpID   Empname Grosspay_ytd    net_pay_ytd Grosspay_mtd    netpay_mtd
------- ------- --------------- ----------- --------------- -----------
164021  Balajee 300             200         600             400

【问题讨论】:

  • 你认为有人会出现在这里问一个对他们来说不是高优先级的问题吗?假设您的问题应该比其他任何人的问题都优先处理,这是不礼貌的。
  • 感谢不信者达米安提供的信息

标签: sql sql-server tsql sql-server-2008-r2 pivot


【解决方案1】:

您可以使用 PIVOT 函数来获取结果,但是问题的一部分是您有两列要在两列中旋转。

由于要透视的数据位于两列中,因此您可以通过多种方式获得结果。您可以将聚合函数与 CASE 表达式一起使用:

select empid, empname,
  sum(case when dur_type='YTD' then gross_pay else 0 end) gross_pay_ytd,
  sum(case when dur_type='YTD' then net_pay else 0 end) net_pay_ytd,
  sum(case when dur_type='MTD' then gross_pay else 0 end) gross_pay_mtd,
  sum(case when dur_type='MTD' then net_pay else 0 end) net_pay_mtd
from yt
group by empid, empname;

SQL Fiddle with Demo

如果您想使用 PIVOT 函数,那么您可以 UNPIVOT gross_paynet_pay 列中的数据,以便数据存在于一列中,然后应用 PIVOT 函数。由于您使用的是 SQL Server 2008,因此您可以使用带有 VALUES 子句的 CROSS APPLY 来反透视数据:

select empid, empname, col+'_'+dur_type as col, value
from yt
cross apply 
(
  values
    ('gross_pay', gross_pay), ('net_pay', net_pay)
) c (col, value)

Demo。这会将当前数据转换为结果:

|  EMPID | EMPNAME |           COL | VALUE |
--------------------------------------------
| 164021 | Balajee | gross_pay_YTD |   100 |
| 164021 | Balajee |   net_pay_YTD |   100 |
| 164021 | Balajee | gross_pay_YTD |   200 |
| 164021 | Balajee |   net_pay_YTD |   100 |

如您所见,我们知道每个员工都有多行,其中一列包含 您想要在最终数据透视结果中的列的名称。当您应用 PIVOT 函数时,代码将是:

select empid, empname,
  gross_pay_ytd, net_pay_ytd, gross_pay_mtd, net_pay_mtd
from
(
  select empid, empname, col+'_'+dur_type as col, value
  from yt
  cross apply 
  (
    values
      ('gross_pay', gross_pay), ('net_pay', net_pay)
  ) c (col, value)
) d
pivot
(
  sum(value)
  for col in (gross_pay_ytd, net_pay_ytd, gross_pay_mtd, net_pay_mtd)
) piv;

SQL Fiddle with Demo。这个版本和CASE版本都会给出结果:

|  EMPID | EMPNAME | GROSS_PAY_YTD | NET_PAY_YTD | GROSS_PAY_MTD | NET_PAY_MTD |
--------------------------------------------------------------------------------
| 164021 | Balajee |           300 |         200 |           600 |         400 |

【讨论】:

    【解决方案2】:

    试试这个 sql。

    select empid,empname,sum(case dur_type when dur_type='YTD' then gross_pay else 0 END)as grosspay_ytd,
    sum(case when dur_type='MTD' then gross_pay else 0 END) as grosspay_mtd  ,
    sum(case when dur_type='YTD' then net_pay else 0 END) as netpay_ytd,
    sum(case when dur_type='MTD' then net_pay else 0 END) as netpay_mtd
    from employee
    group by empid,empname,dur_type
    

    【讨论】:

    • 感谢您的回复,我已经通过添加案例来做到这一点,但需要知道我们是否可以使用枢轴来做到这一点?
    • 这样嵌套聚合是不可能的。
    • @Pheonix 这在 SQL 服务器中不起作用。不允许嵌套聚合,它会抛出错误消息 -- 参见这个演示 -- sqlfiddle.com/#!3/576d9/10
    • @bluefeet :在你的小提琴中尝试过,但没有用。我以前在mysql中做过这个。所以我认为它可能也适用于这里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多