oracle中的解码语句内的子查询

时间:2019-10-10 16:16:05

标签: sql oracle

我的数据如下表所示:

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, 然后使用max(start_dtm)和end_dtm为null的employee_num打印

如果没有条目以NULL作为end_dtm, 然后使用end_dtm = max(end_dtm)打印employee_num

我尝试过

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 个答案:

答案 0 :(得分:1)

因此,您必须先区分END_DTM为空还是非空,然后才考虑使用END_DTM或START_DTM进行进一步排序。

对于第一部分,功能NVL2正是您所需要的。它需要三个参数。当第一个参数为非null时,它将返回第二个参数,而当第三个参数为null时,它将返回第三个参数。因此:如果日期不为null,则NVL2(END_DTM,1,0)将返回1,如果日期为null,则返回0。然后,您可以再次使用NVL2,当它不为空时选择END_DTM,但当它不为空时选择START_DTM。

然后可以在ORDER BY子句中使用它来定义ROW_NUMBER(),如下所示:

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。

答案 1 :(得分:0)

我本可以使用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;

干杯!

答案 2 :(得分:-1)

只需使用聚合和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;