从SQL中的一行中的不同列中选择最高日期

时间:2017-06-12 15:14:43

标签: sql oracle

我有一个包含大量日期的表,数据列中也包含空值。我如何找到其中最伟大的?

表名为JOB_DATE_VALUES。对于不同分支机构的员工,列为JOB_START_DT,JOB_END_DT,JOB_PROMO_DT,JOB_DEMO_DT。我需要找到特定分支中员工的最长日期。表格如下

ROW_ID EMP_NM DEPT_NM JOB_START_DT JOB_END_DT JOB_PROMO_DT JOB_DEMO_DT
1-E4   123   SALES    11-NOV-2014             10-OCT-2015  
1-E5   234   FIN      01-JAN-2013             01-JAN-2015 

我使用LEAST,GREATEST,它们只返回NULL值。所以,请告诉我。

3 个答案:

答案 0 :(得分:1)

您可以使用greatest替换null值。

select greatest(
 nvl(to_date(JOB_START_DT,'DD-MON-YYYY'),to_date('01-01-1900','DD-MM-YYYY'))
,nvl(to_date(JOB_END_DT,'DD-MON-YYYY'),to_date('01-01-1900','DD-MM-YYYY'))
,nvl(to_date(JOB_PROMO_DT,'DD-MON-YYYY'),to_date('01-01-1900','DD-MM-YYYY'))
,nvl(to_date(JOB_DEMO_DT,'DD-MON-YYYY'),to_date('01-01-1900','DD-MM-YYYY'))
) as grtst_date
from tbl

答案 1 :(得分:1)

要管理Null值,您可以使用COALESCE表达式,它是CASE表达式的语法快捷方式:

GREATEST(
    COALESCE(JOB_START_DT, JOB_END_DT, JOB_PROMO_D, JOB_DEMO_DT),
    COALESCE(JOB_END_DT, JOB_PROMO_D, JOB_DEMO_DT, JOB_START_DT),
    COALESCE(JOB_PROMO_D, JOB_DEMO_DT, JOB_START_DT, JOB_END_DT),
    COALESCE(JOB_DEMO_DT, JOB_START_DT, JOB_END_DT, JOB_PROMO_D)
)

答案 2 :(得分:1)

如您所知(或者您发现此练习),LEAST和GREATEST的工作方式与MIN和MAX不同。对于连续而不是列的值,它们似乎也做同样的事情。但MIN和MAX忽略空值,而LEAST和GREATEST则不然。

利用MIN和MAX(而不是LEAST和GREATEST)的一种方法是对基表进行UNPIVOT,然后使用标准聚合。但是警告:基表中的数据已经“按行”分组。通过取消隐藏,您将丢失该信息,并且Oracle需要再次分组,就像数据尚未分组一样。

select row_id, emp_nm, dept_nm, max(dt) as most_recent_date
from   job_date_values
unpivot ( dt for descr in (job_start_dt, job_end_dt, job_promo_dt, job_demo_dt))
group by row_id, emp_nm, dept_nm
;

ROW_  EMP_NM  DEPT_NM  MOST_RECENT_DATE
----  ------  -------  ----------------
1-E4     123  SALES    10-OCT-2015     
1-E5     234  FIN      01-JAN-2015  

这种方法的一个优点是,您还可以包含最新的日期类型(是job_start_date?job_promo_date?等)您可以通过添加SELECT子句来实现:

select row_id, ... , ... as most recent_date, 
       max(descr) keep (dense_rank last order by dt) as descr