聚合水平SQL数据

时间:2016-12-13 16:27:49

标签: sql sql-server

我需要总结在Microsoft SQL数据库中水平扩展的数据。

+-------+---------+----------+---------+----------+---------+----------+---------+
| JOB   | DATE    | CC1_CODE | CC1_HRS | CC2_CODE | CC2_HRS | CC3_CODE | CC3_HRS |
+-------+---------+----------+---------+----------+---------+----------+---------+
| A1234 | 12/1/16 | 0100     | 6       | 0300     | 2       | NULL     | 0       |  
+-------+---------+----------+---------+----------+---------+----------+---------+
| A1234 | 12/1/16 | 0200     | 8       | NULL     | 0       | NULL     | 0       |
+-------+---------+----------+---------+----------+---------+----------+---------+     
| A1234 | 12/1/16 | 0100     | 4       | 0200     | 2       | 0300     | 2       |
+-------+---------+----------+---------+----------+---------+----------+---------+

期望的结果是 - 按JOB和DATE分组,然后通过CODE汇总所有HRS。

+-------+---------+----------+---------+----------+---------+----------+---------+
| JOB   | DATE    | CC1_CODE | CC1_HRS | CC2_CODE | CC2_HRS | CC3_CODE | CC3_HRS |
+-------+---------+----------+---------+----------+---------+----------+---------+
| A1234 | 12/1/16 | 0100     | 10      | 0200     | 10      | 0300     | 4       |  
+-------+---------+----------+---------+----------+---------+----------+---------+

备注 - 列实际上从CC1转到CC25。 CC_CODES可以存储在任何CC_CODES字段中,它只取决于首先进入哪个。

1 个答案:

答案 0 :(得分:1)

令人讨厌的数据格式。一种方法是取消数据,然后重新聚合:

select job, date, code, sum(hrs) as hrs
from t cross apply
     (values (CC1_CODE, CC1_HRS),
             (CC2_CODE, CC2_HRS),
             . . .
     ) c(code, hrs)
group by job, date, code;

我认为没有理由继续尝试以该格式处理数据。以上内容返回不同行的数据。

但是,如果你真的必须,这是一个使用条件聚合的方法(和上面的查询):

with a as (
      select job, date, code, sum(hrs) as hrs,
             row_number() over (partition by job, date order by code) as seqnum
      from t cross apply
           (values (CC1_CODE, CC1_HRS),
                   (CC2_CODE, CC2_HRS),
                   . . .
           ) c(code, hrs)
      group by job, date, code
     )
select job, date,
       max(case when seqnum = 1 then code end) as code_01,
       max(case when seqnum = 1 then hrs end) as hrs_01,
       max(case when seqnum = 2 then code end) as code_02,
       max(case when seqnum = 2 then hrs end) as hrs_02,
       . . .
from a
group by job, date;