Подзапрос внутри оператора декодирования в Oracle - PullRequest
0 голосов
/ 10 октября 2019

У меня есть данные в таблице, как показано ниже:

EMPLOYEE_NUM              START_DTM             END_DTM
47567567446          5/9/2019 12:00:00 PM   
76475676575675756    5/10/2019 12:00:00 PM  5/10/2019 11:59:59 PM
456756765767         5/3/2019 12:00:00 PM   5/8/2019 11:59:59 PM
74676576764565       5/2/2019 12:00:00 PM   5/8/2019 11:59:59 PM
98695689576          5/1/2019 12:00:00 PM   

Я хочу получить employee_num с условиями ниже:

, если есть какие-либо записи с NULL в качестве end_dtm, то выведите employee_num с max(start_dtm) и значение end_dtm которого равно нулю

, если нет записей с NULL в качестве end_dtm, то выведите employee_num с end_dtm = max (end_dtm)

Я пытался с

select 
decode(select count(1) from employee where end_dtm is null,
       0,
       select employee_num where end_dtm=(select max(end_dtm) from employee),
       select employee_num where start_dtm=(select max(start_dtm) from employee where end_dtm is null),
       ) from dual

Похоже, это неверный запрос. Может ли кто-нибудь, пожалуйста, помогите.

Ответы [ 3 ]

1 голос
/ 10 октября 2019

Таким образом, вы должны различать, что END_DTM сначала является нулевым, а не ненулевым, и только затем следует рассмотреть либо END_DTM, либо START_DTM для дальнейшего упорядочения.

Функция NVL2 - это именно то, что вам нужно для первой части. Требуется три аргумента;он возвращает второй аргумент, когда первый не равен нулю, и третий аргумент, когда он равен нулю. Итак: NVL2 (END_DTM, 1, 0) вернет 1, если дата не равна нулю, и 0, если она равна нулю. И затем, вы можете снова использовать NVL2, чтобы выбрать END_DTM, когда он не нулевой, а START_DTM, когда он нулевой.

Затем вы можете использовать это при определении ROW_NUMBER (), в предложении ORDER BY, например, так:

select [whatever]
from   
  ( select t.*, 
           row_number() over (order by nvl2(END_DTM, 1, 0),
                                       nvl2(END_DTM, END_DTM, START_DTM) desc) rn
    from   your_table t
  )
where  rn = 1
;

Если END_DTM всегда не равен нулю (или если он всегда равен нулю), то первое значение NVL2 является постоянным, поэтому упорядочение выполняется только по END_DTM (если END_DTM всегда не равно нулю),соответственноSTART_DTM (если END_DTM всегда равен нулю). Но если есть сочетание нулевого и ненулевого END_DTM, то только критерии с нулевым END_DTM связываются по первому критерию упорядочения, и затем для выбора максимального значения START_DTM рассматриваются только эти строки.

0 голосов
/ 10 октября 2019

Просто используйте агрегирование и case:

select employee_num,
       (case when count(*) = count(end_dtm)  -- no nulls
             then max(end_dtm)
             else max(start_dtm)
        end)
from t
group by employee_num;

Если вы хотите это для строки в исходных данных, используйте аналитические функции:

select t.*,
       (case when count(*) over (partition by employee_num) = count(end_dtm) over (partition by employee_num)  -- no nulls
             then max(end_dtm) over (partition by employee_num)
             else max(start_dtm) over (partition by employee_num)
        end)
from t;

РЕДАКТИРОВАТЬ:

Альтернативное прочтение того, что вы хотите, предполагает, что вы хотите один employee_num подзапрос к вашим условиям. Если это так, то это еще проще:

select t.*
from (select t.*
      from t
      order by (case when end_dtm is null then 1 else 2 end),  -- nulls first
               start_dtm desc
     ) t
where rownum = 1;
0 голосов
/ 10 октября 2019

Я бы использовал для этого функцию analytical следующим образом:

Select employee_num from
(Select t.employee_num
Sum(case when end_dtm is null then 1 end) as cnt,
Row_number() 
over (order by end_dtm desc nulls last) as end_dtm_rn,
Row_number() 
over (order by case when end_dtm is null then start_dtm end desc nulls last) as start_dtm_rn
From employee t)
Where case when cnt = 0 
then end_dtm_rn
Else start_dtm_rn end = 1;

Cheers !!

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