使用 case 条件将多列转置为行

湿婆

我在下面有一个 SQL 查询

select 
row_number()
OVER (ORDER BY hapf.position_code) Identifier,
hapf.position_code as position_code,
pg.name as gradename,
pgsfv.name as stepname
from
hr_all_positions_f hapf, PER_VALID_GRADES_F pvgf, per_grades pg, PER_GRADE_STEPS_F_VL pgsfv
where
hapf.position_id = pvgf.position_id
and pvgf.grade_id = pg.grade_id
and pgsfv.grade_id = pg.grade_id
and hapf.position_code = 'PRGUSPOS084'
and TO_CHAR(hapf.effective_end_date, 'YYYY-MM-DD') = '4712-12-31'

输出低于

Identifier  Position_Code  Gradename  Stepname
1           PRGUSPOS084    Salary05   Step01
2           PRGUSPOS084    Salary05   Step02
3           PRGUSPOS084    Salary05   Step03
4           PRGUSPOS084    Salary06   Step01
5           PRGUSPOS084    Salary06   Step02
6           PRGUSPOS084    Salary06   Step03
7           PRGUSPOS084    Salary07   Step01
8           PRGUSPOS084    Salary07   Step02
9           PRGUSPOS084    Salary07   Step03

我已经使用了条件将 GradeName 列转换为如下行的情况

SQL

    select 
row_number()
OVER (ORDER BY position_code) RN,
position_code as pos,
--stepname as step,
max(case when Identifier = 1 then gradename end) as Grade1,
max(case when Identifier = 2 then gradename end) as Grade2,
max(case when Identifier = 3 then gradename end) as Grade3
from
(
select 
row_number()
OVER (ORDER BY hapf.position_code) Identifier,
hapf.position_code as position_code,
pg.name as gradename,
pgsfv.name as stepname
from
hr_all_positions_f hapf, PER_VALID_GRADES_F pvgf, per_grades pg, PER_GRADE_STEPS_F_VL pgsfv
where
hapf.position_id = pvgf.position_id
and pvgf.grade_id = pg.grade_id
and pgsfv.grade_id = pg.grade_id
and hapf.position_code = 'PRGUSPOS084'
and TO_CHAR(hapf.effective_end_date, 'YYYY-MM-DD') = '4712-12-31'
) x
group by position_code

此查询的输出如下

RN  POS           GRADE1      GRADE2      GRADE3
1   PRGUSPOS084   Salary 05   Salary 06   Salary 07

但我想输出如下

NO  POS           GRADE1      GRADE2      GRADE3       Grade1Step1    Grade1Step2    Grade1Step3    Grade2Step1    Grade2Step2    Grade2Step3    Grade3Step1    Grade3Step2    Grade3Step3
1   PRGUSPOS084   Salary 05   Salary 06   Salary 07    Step01         Step02         Step03         Step01         Step02         Step03         Step01         Step02         Step03

怎么可能使用另一个 case 语句?

我尝试了以下但输出不正确,请帮助。

    select
pos,
Grade1,
Grade2,
Grade3, 
max(case when RN = 1 then step end) as stepname1,
max(case when RN = 2 then step end) as stepname2,
max(case when RN = 3 then step end) as stepname3
from
(
    select 
    row_number()
    OVER (ORDER BY position_code) RN,
    position_code as pos,
    stepname as step,
    max(case when Identifier = 1 then gradename end) as Grade1,
    max(case when Identifier = 2 then gradename end) as Grade2,
    max(case when Identifier = 3 then gradename end) as Grade3
    from
    (
    select 
    row_number()
    OVER (ORDER BY hapf.position_code) Identifier,
    hapf.position_code as position_code,
    pg.name as gradename,
    pgsfv.name as stepname
    from
    hr_all_positions_f hapf, PER_VALID_GRADES_F pvgf, per_grades pg, PER_GRADE_STEPS_F_VL pgsfv
    where
    hapf.position_id = pvgf.position_id
    and pvgf.grade_id = pg.grade_id
    and pgsfv.grade_id = pg.grade_id
    and hapf.position_code = 'PRGUSPOS084'
    and TO_CHAR(hapf.effective_end_date, 'YYYY-MM-DD') = '4712-12-31'
    ) x
    group by position_code
    , stepname
) z group by pos, Grade1, Grade2, Grade3
亚历克斯·普尔

您可以在内部查询中调用多个分析函数,使用不同的partition-by 子句,而不仅仅是一个;然后从这些开始工作 - 结合案例表达式中等级和步骤的分析排名。

由于我没有您的基本表,因此我从您的示例中给出了固定值作为进一步的内部查询来演示这个想法,并使用一个额外的值来显示第二行输出:

select position_num,
  position_code,
  max(case when grade_num = 1 then grade_name end) as grade1,
  max(case when grade_num = 2 then grade_name end) as grade2,
  max(case when grade_num = 3 then grade_name end) as grade3,
  max(case when grade_num = 1 and grade_step_num = 1 then step_name end) as Grade1Step1,
  max(case when grade_num = 1 and grade_step_num = 2 then step_name end) as Grade1Step2,
  max(case when grade_num = 1 and grade_step_num = 3 then step_name end) as Grade1Step3,
  max(case when grade_num = 2 and grade_step_num = 1 then step_name end) as Grade2Step1,
  max(case when grade_num = 2 and grade_step_num = 2 then step_name end) as Grade2Step2,
  max(case when grade_num = 2 and grade_step_num = 3 then step_name end) as Grade2Step3,
  max(case when grade_num = 3 and grade_step_num = 1 then step_name end) as Grade3Step1,
  max(case when grade_num = 3 and grade_step_num = 2 then step_name end) as Grade3Step2,
  max(case when grade_num = 3 and grade_step_num = 3 then step_name end) as Grade3Step3
from (
  select 
    dense_rank() over (order by position_code) position_num,
    position_code,
    grade_name,
    step_name,
    dense_rank() over (partition by position_code order by grade_name) as grade_num,
    dense_rank() over (partition by position_code, grade_name order by step_name) as grade_step_num
  from
  (
    select 'PRGUSPOS084' as position_code, 'Salary05' as grade_name, 'Step01' as step_name from dual
    union all select 'PRGUSPOS084', 'Salary05', 'Step02' from dual
    union all select 'PRGUSPOS084', 'Salary05', 'Step03' from dual
    union all select 'PRGUSPOS084', 'Salary06', 'Step01' from dual
    union all select 'PRGUSPOS084', 'Salary06', 'Step02' from dual
    union all select 'PRGUSPOS084', 'Salary06', 'Step03' from dual
    union all select 'PRGUSPOS084', 'Salary07', 'Step01' from dual
    union all select 'PRGUSPOS084', 'Salary07', 'Step02' from dual
    union all select 'PRGUSPOS084', 'Salary07', 'Step03' from dual
    union all select 'PRGUSPOS085', 'Salary06', 'Step02' from dual
  )
)
group by position_num, position_code;

得到:

POSITION_NUM POSITION_CO GRADE1   GRADE2   GRADE3   GRADE1 GRADE1 GRADE1 GRADE2 GRADE2 GRADE2 GRADE3 GRADE3 GRADE3
------------ ----------- -------- -------- -------- ------ ------ ------ ------ ------ ------ ------ ------ ------
           1 PRGUSPOS084 Salary05 Salary06 Salary07 Step01 Step02 Step03 Step01 Step02 Step03 Step01 Step02 Step03
           2 PRGUSPOS085 Salary06                   Step02                                                        

所以你真正的查询最终可能是这样的:

select position_num,
  position_code,
  max(case when grade_num = 1 then grade_name end) as grade1,
  max(case when grade_num = 2 then grade_name end) as grade2,
  max(case when grade_num = 3 then grade_name end) as grade3,
  max(case when grade_num = 1 and grade_step_num = 1 then step_name end) as Grade1Step1,
  max(case when grade_num = 1 and grade_step_num = 2 then step_name end) as Grade1Step2,
  max(case when grade_num = 1 and grade_step_num = 3 then step_name end) as Grade1Step3,
  max(case when grade_num = 2 and grade_step_num = 1 then step_name end) as Grade2Step1,
  max(case when grade_num = 2 and grade_step_num = 2 then step_name end) as Grade2Step2,
  max(case when grade_num = 2 and grade_step_num = 3 then step_name end) as Grade2Step3,
  max(case when grade_num = 3 and grade_step_num = 1 then step_name end) as Grade3Step1,
  max(case when grade_num = 3 and grade_step_num = 2 then step_name end) as Grade3Step2,
  max(case when grade_num = 3 and grade_step_num = 3 then step_name end) as Grade3Step3
from (
  select 
    dense_rank() over (order by hapf.position_code) position_num,
    hapf.position_code,
    pg.name as grade_name,
    pgsfv.name as step_name,
    dense_rank() over (partition by hapf.position_code order by pg.name) as grade_num,
    dense_rank() over (partition by hapf.position_code, pg.name order by pgsfv.name)
      as grade_step_num
  from
  hr_all_positions_f hapf
  join per_valid_grades_f pvgf on hapf.position_id = pvgf.position_id
  join per_grades pg on pvgf.grade_id = pg.grade_id
  join per_grade_steps_f_vl pgsfv on pgsfv.grade_id = pg.grade_id
  where hapf.position_code = 'PRGUSPOS084'
  and hapf.effective_end_date = date '4712-12-31'
)
group by position_num, position_code;

我冒昧地将您的内部查询切换为使用现代连接语法;并将您effective_end_date的日期与实际日期进行比较,而不是将其转换为字符串 - 这通常是一个坏主意,因为它会阻止使用该列的索引。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章