Транспонировать несколько столбцов в строки, используя условие case - PullRequest
0 голосов
/ 10 сентября 2018

У меня 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

1 Ответ

0 голосов
/ 10 сентября 2018

Вы можете вызывать несколько аналитических функций внутри вашего внутреннего запроса, с разными предложениями по разделению вместо одной; а затем поработайте над ними - прочесав аналитическое ранжирование оценок и шагов в выражениях падежа.

Поскольку у меня нет ваших базовых таблиц, я дал фиксированные значения из вашего образца в качестве дополнительного внутреннего запроса, чтобы продемонстрировать идею, с одним дополнительным значением, чтобы показать вторую строку вывода:

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 с фактической датой, а не преобразовывать ее в строку - что, как правило, является плохой идеей, поскольку не позволяет использовать индекс для этого столбца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...