用于数据透视的SQL

编程语言 2026-07-10

我在SQL Server中创建了一个视图;它基本上就是一个工资单表,同一月的同一名员工会有多条记录。

我想把整份数据合并成单行,即每位员工一行。每位员工可能有,也可能没有加班(OT)。

员工编号 工资单号 工资单日期 小时数 基本工资 住房津贴 班次 子女 加班1 加班2 加班3 总工资
123456 3456 31/03/2021 0 NULL 123 456 321 NULL NULL NULL 900
123456 3456 31/03/2021 162.23 1234 NULL NULL NULL NULL NULL NULL 1234
123456 3456 31/03/2021 12.25 NULL NULL NULL NULL NULL 240 NULL 240
123456 3456 31/03/2021 10 NULL NULL NULL NULL 120 NULL NULL 120

期望的输出如下:

员工编号 工资单号 工资单日期 基本工资 基本工资时数 住房津贴 班次 子女 加班1 加班1时数 加班2 加班2时数 加班3 加班3时数 总工资
123456 3456 31/03/2021 1234 162.23 123 456 321 120 10 240 12.25 0 0 2494

如何在SQL Server中实现?

解决方案

正如其他人已经提到的,你是在寻找常规聚合和条件聚合的组合。条件聚合在聚合函数内部使用CASE表达式。

-- Sample data - which will come from the view in your case
with cte as (
  select *
  from (
    values
    (123456, 3456, '31/03/2021', 0, null, 123, 456, 321, cast(null as int), cast(null as int), cast(null as int), 900)
    , (123456, 3456, '31/03/2021', 162.23, 1234, null, null, null, null, null, null, 1234)
    , (123456, 3456, '31/03/2021', 12.25, null, null, null, null, null, 240, null, 240)
    , (123456, 3456, '31/03/2021', 10, null, null, null, null, 120, null, null, 120)
  ) x (Employee_ID, PSNO, PSDATE, HOURS, BASIC, HRA, SHIFT, CHILD, OT1, OT2, OT3, GROSS)
)
-- The query which returns your desired results
select Employee_ID, PSNO, PSDATE
  , isnull(max(BASIC), 0) BASIC
  , max(case when BASIC is not null then HOURS end 0 end) BASIC_HRS
  , max(HRA) HRA
  , max(SHIFT) SHIFT
  , max(CHILD) CHILD
  , isnull(max(OT1), 0) OT1
  , max(case when OT1 is not null then HOURS else 0 end) OT1_HRS
  , isnull(max(OT2), 0) OT2
  , max(case when OT2 is not null then HOURS else 0 end) OT2_HRS
  , isnull(max(OT3), 0) OT3
  , max(case when OT3 is not null then HOURS else 0 end) OT3_HRS
  , sum(GROSS) GROSS
from cte
group by Employee_ID, PSNO, PSDATE;

db<>fiddle

备注:这种条件聚合的形式只有在你确定被聚合的多行中,某一列只有一个正的有效值用于条件聚合时才会起作用。max 函数随后会正确地选择这个唯一的正值。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章