Oracle SQL Как мне написать это Join с меньшим количеством кода? - PullRequest
0 голосов
/ 30 августа 2018

Здравствуйте, эксперты Oracle. У меня вопрос о том, как правильно объединить две таблицы.

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

PTRLVAC_LCAT_CODE   PTRLVAC_YEAR    PTRLVAC_ROLL_MAX_HRS
C1                  0               80                  
C1                  2               88
C1                  5               128
P3                  0               120
P3                  2               128
P3                  5               168

В следующей таблице указаны идентификатор сотрудника, дата найма и категория ухода

PEBEMPL_PIDM    PEBEMPL_HIRE_DATE   PEBEMPL_LCAT_CODE  
1234            01/09/2017          P3
3214            02/01/2014          C1

Объединение, которое у меня есть сейчас, основано на CTE, и я не уверен, является ли это самым простым решением. ** Я включил таблицы здесь как CTE

with ptrlvac as(
    select 'C1' ptrlvac_lcat_code
          ,0 ptrlvac_year
          ,80 ptrlvac_roll_max_hrs
    from dual union all
    select 'C1', 2, 88 from dual union all
    select 'C1', 5, 128 from dual union all
    select 'P3', 0, 120 from dual union all
    select 'P3', 5, 128 from dual union all
    select 'P3', 2, 168 from dual
    ) , pebempl as(
    select 1234 pebempl_pidm
          ,to_date('09-JAN-2017', 'DD-MON-YYYY') pebempl_hire_date
          ,'P3' pebempl_lcat_code
    from dual
    UNION ALL
    select 3214, to_date('01-FEB-2014','DD-MON-YYYY'), 'C1' from dual
) ,leave as(
    select a.ptrlvac_lcat_code
          ,a.ptrlvac_year
          ,a.ptrlvac_roll_max_hrs
          ,row_number()
              over(partition by a.ptrlvac_lcat_code
                   order by a.ptrlvac_year) rn
    from ptrlvac a
    )
,leave_rules as(
    select a.ptrlvac_lcat_code
          ,a.ptrlvac_year year_start
          ,nvl(b.ptrlvac_year, 100)-1 year_end
          ,a.ptrlvac_roll_max_hrs
    from leave a
         left join leave b
         on  a.ptrlvac_lcat_code = b.ptrlvac_lcat_code
         and a.rn = b.rn - 1
    )
select distinct pebempl_pidm
          ,pebempl_hire_date
          ,floor(months_between(to_date(:seldate, 'DD-MON-YYYY'), pebempl_hire_date) / 12)  as service_years
          ,pebempl_lcat_code as lcat
          ,b.ptrlvac_roll_max_hrs
    from pebempl a
         inner join leave_rules b
         on a.pebempl_lcat_code = b.ptrlvac_lcat_code
         and floor(months_between(to_date(:seldate, 'DD-MON-YYYY'), pebempl_hire_date) / 12) between b.year_start and b.year_end

Любая помощь в сохранении некоторых нажатий будет принята с благодарностью.

Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

Я не уверен, что это то, что вы хотите:

select
t2.PEBEMPL_PIDM,
t1.PTRLVAC_ROLL_MAX_HRS
from test1 t1, test2 t2
where
t1.PTRLVAC_LCAT_CODE = t2.PEBEMPL_LCAT_CODE and
t1.PTRLVAC_YEAR = 
(select max(t1s.PTRLVAC_YEAR) from test1 t1s
where t1s.PTRLVAC_LCAT_CODE = t2.PEBEMPL_LCAT_CODE
and (sysdate-PEBEMPL_HIRE_DATE)/365 >= t1s.PTRLVAC_YEAR);

Вот результаты, полученные на основе ваших тестовых данных:

PEBEMPL_PIDM PTRLVAC_ROLL_MAX_HRS                                               
------------ --------------------                                               
        3214                   88                                               
        1234                  120                                               

Бобби

0 голосов
/ 31 августа 2018

Обдумал ли это обед, еще больше сократив ответ @ BobbyDurret:

select
t2.PEBEMPL_PIDM,
max(t1.PTRLVAC_ROLL_MAX_HRS)
from ptrlvac t1, pebempl t2
where
t1.PTRLVAC_LCAT_CODE = t2.PEBEMPL_LCAT_CODE and
(sysdate-PEBEMPL_HIRE_DATE)/365 >= t1.PTRLVAC_YEAR
group by t2.PEBEMPL_PIDM

Предполагается, что Max_Hrs всегда увеличивается на более долгий срок службы.

0 голосов
/ 30 августа 2018

Вместо использования row_number и фильтрации в отдельном CTE используйте lead:

with leave_rules as
(
    select a.ptrlvac_lcat_code
          ,a.ptrlvac_year as year_start
          ,a.ptrlvac_roll_max_hrs
          ,lead(ptrlvac_year,1,10000) over (partition by ptrlvac_lcat_code
                                 order by ptrlvac_year)
          as year_end
    from ptrlvac a
)
select distinct pebempl_pidm
          ,pebempl_hire_date
          ,floor(months_between(sysdate, pebempl_hire_date) / 12)  as service_years
          ,pebempl_lcat_code as lcat
          ,b.ptrlvac_roll_max_hrs
    from pebempl a
         inner join leave_rules b
         on a.pebempl_lcat_code = b.ptrlvac_lcat_code
         and floor(months_between(sysdate, pebempl_hire_date) / 12) between year_start and year_end

Объединяет ваши 2 CTE для вычисления "left_rules" в 1. Я просто поместил sysdate для переменной даты, чтобы я мог легко протестировать - вы, вероятно, захотите использовать переменные связывания, как у вас было изначально.

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