Oracle中where子句中的case表达式

Posted

技术标签:

【中文标题】Oracle中where子句中的case表达式【英文标题】:Case expression in where clause in Oracle 【发布时间】:2018-09-12 05:30:49 【问题描述】:

我根据某些条件从 Oracle 表中提取了一些数据。

如果 JobFunctionCode = 'ADMIN' 的人在他辞职时会填充 notify_termination_date,然后他的数据就会被提取。

来自其他 JobFunctionCode 的人(如经理、财务等)在他们辞职时填充了接受的终止日期,然后他们的数据应该被提取。

因此,根据这些条件提取数据,我在WHERE 子句中编写了一个案例语句,但它给出了缺少括号的错误。此 SQL 是计划运行,因此我已将终止日期设置为 sysdate,它将每天运行。

select ppos.person_id, paam.position_id, pjf.job_function_code 
from 
    per_all_assignments_m paam, per_periods_of_service ppos, per_jobs_f pjf
    where
    case
        when    pjf.job_function_code = 'ADMIN' then (TO_CHAR(ppos.notified_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD'))
        else    (TO_CHAR(ppos.accepted_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD'))
    end
    and paam.person_id = ppos.person_id
    and paam.job_id = pjf.job_id
    and paam.primary_flag = 'Y'
    and TO_CHAR(paam.effective_end_date, 'YYYY-MM-DD') = '4712-12-31'
    and TO_CHAR(pjf.effective_end_date, 'YYYY-MM-DD') = '4712-12-31'

另外,当两个 JobFunctionCode 中的 Person 终止时,可能会出现两个 person 数据都应该被拉出的情况,所以我认为在这种情况下不能使用 CASE 表达式。

请告诉我这里的逻辑怎么写?

【问题讨论】:

所以,如果管理员在 notify_termination_date 辞职而其他 jobFunctionCode 在接受的termination_date 辞职,基本上你需要获取数据。有要求吗? 是的,而且如果 JobFunctionCode 'ADMIN' 的人 A 和 JobFunctionCode 'MANAGER' 的人 B 在同一天辞职,那么这两个人的数据都应该来,某种 OR 逻辑..可能是.. 【参考方案1】:

where 子句应该是:

where
(
    (pjf.job_function_code = 'ADMIN' and TO_CHAR(ppos.notified_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD'))
    or (pjf.job_function_code <> 'ADMIN' and TO_CHAR(ppos.accepted_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD'))
)
and <rest of clauses>

我还没有查看其余部分,是否需要 TO-CHAR 等,但这将修复您的 where 子句。

【讨论】:

【参考方案2】:

你可以试试:

((case 
   when pjf.job_function_code = 'ADMIN'
       case 
          when (TO_CHAR(ppos.notified_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD')) then 'Y'
          else 'N'
       end
   else 
      case  
         when (TO_CHAR(ppos.accepted_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD')) then 'Y'
         else 'N'
      end
end )='Y'  
or exists (select * from <<tablename>> pjf.job_function_code = 'ADMIN' 
and (TO_CHAR(ppos.notified_termination_date, 'YYYY-MM-DD')) = (TO_CHAR(ppos.accepted_termination_date, 'YYYY-MM-DD'))));

P.S: 只需检查括号闭包,并根据您的表设计将查询写入存在子句中

【讨论】:

【参考方案3】:

where子句不允许的情况下,您可以在下面写下您的条件

where       
   ( pjf.job_function_code = 'ADMIN' AND 
  (TO_CHAR(ppos.notified_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD'))
    Or    (TO_CHAR(ppos.accepted_termination_date, 'YYYY-MM-DD') = TO_CHAR(SYSDATE, 'YYYY-MM-DD'))
    )
and paam.person_id = ppos.person_id
and paam.job_id = pjf.job_id
and paam.primary_flag = 'Y'
and TO_CHAR(paam.effective_end_date, 'YYYY-MM-DD') = '4712-12-31'
and TO_CHAR(pjf.effective_end_date, 'YYYY-MM-DD') = '4712-12-31'

【讨论】:

以上是关于Oracle中where子句中的case表达式的主要内容,如果未能解决你的问题,请参考以下文章

Where 子句 TSQL 中的 case 表达式

WHERE子句中的SQL Server CASE表达式以检查NULL值

where 子句 oracle 中的 case 语句

Oracle:在 Where 子句中使用 Case 语句

Oracle SQL 不同的 where 子句与 case when

CASE表达式