简体   繁体   English

SQL / PLSQL Oracle查询:WHERE语句中的CASE

[英]SQL/PLSQL Oracle query: CASE in WHERE statement

I am attempting to query an oracle db but cant quite get the script to work. 我正在尝试查询oracle数据库,但无法完全使脚本正常工作。 The script is meant to search for employees with a start_date between two dates. 该脚本是为了寻找员工提供一个start_date两个日期之间。 Unfortunately, not all employees have a start_date in the database, but all employees have a create_date . 不幸的是,并非所有员工在数据库中都有start_date ,但是所有员工都具有create_date What I would like to do is: 我想做的是:

IF START_DATE IS NULL:
    (E.START_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.START_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY')
ELSE: 
    (E.CREATE_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.CREATE_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY')

Here is what I have so far: 这是我到目前为止的内容:

SELECT OC.DESCRIPTION "Description",
sum(S.AMOUNT) "SUM",
COUNT (DISTINCT(E.EMPLOYEE_NUM)) "Employee Nums"
FROM EMPLOYEES E
JOIN EMPLOYEE_SPENDING S ON S.EMPLOYEE_ID = E.EMPLOYEE_ID
WHERE E.EMPLOYEE_CATEGORY IN ('ACTIVE', 'INACTIVE')
AND ((E.START_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.START_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY'))
OR (E.CREATE_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.CREATE_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY')))
GROUP BY E.EMPLOYEE_CATEGORY;

My case statement looked something like this: 我的案例陈述看起来像这样:

SELECT OC.DESCRIPTION "Description",
sum(S.AMOUNT) "SUM",
COUNT (DISTINCT(E.EMPLOYEE_NUM)) "Employee Nums"
FROM EMPLOYEES E
JOIN EMPLOYEE_SPENDING S ON S.EMPLOYEE_ID = E.EMPLOYEE_ID
WHERE E.EMPLOYEE_CATEGORY IN ('ACTIVE', 'INACTIVE')
AND (CASE WHEN E.START_DATE IS NULL THEN (E.START_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.START_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY'))
ELSE (E.CREATE_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.CREATE_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY'))
END
GROUP BY E.EMPLOYEE_CATEGORY;

I'm not super familiar with Oracle or PLSQL, so any help you can provide would be much appreciated! 我对Oracle或PLSQL不太熟悉,因此,您能提供的任何帮助将不胜感激!

Thanks in advance! 提前致谢!

I believe you have the logic backwards. 我相信您的逻辑倒退。 This makes much more sense: 这更有意义:

IF START_DATE IS NOT NULL:
    (E.START_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.START_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY')
ELSE: 
    (E.CREATE_DATE >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND E.CREATE_DATE <= TO_DATE('10/29/2016', 'MM/DD/YYYY')

Then, you can just express this as: 然后,您可以将其表示为:

where (e.start_date >= date '2014-10-29' and e.start_date <= date '2016-10-29') or
      (e.start_date is null and e.create_date >= date '2014-10-29' and e.start_date <= date '2016-10-29')

Notice that I've simplified the "date constant" by using the date keyword followed by an ISO-standard date. 注意,我通过使用date关键字后跟一个ISO标准日期简化了“日期常数”。

This can be further simplified as: 这可以进一步简化为:

where coalesce(e.start_date, e.create_date) >= date '2014-10-29' and
      coalesce(e.start_date, e.create_date) <= date '2016-10-29'

In general, you want to avoid case in where clauses, because basic boolean expressions are usually pretty simple to write and understand. 通常,您要避免在where子句中使用case ,因为基本的布尔表达式通常很容易编写和理解。 The time to use case is when you explicitly want to sequence the conditions, particularly when one condition might be an expensive function call. case的时间是当您明确想要对条件进行排序时,尤其是当一个条件可能是昂贵的函数调用时。

Use nvl like this: 像这样使用nvl:

SELECT OC.DESCRIPTION "Description",
sum(S.AMOUNT) "SUM",
COUNT (DISTINCT(E.EMPLOYEE_NUM)) "Employee Nums"
FROM EMPLOYEES E
JOIN EMPLOYEE_SPENDING S ON S.EMPLOYEE_ID = E.EMPLOYEE_ID
WHERE E.EMPLOYEE_CATEGORY IN ('ACTIVE', 'INACTIVE')
AND ((nvl(E.START_DATE, e.create_date) >= TO_DATE('10/29/2014', 'MM/DD/YYYY') AND (nvl(E.START_DATE, e.create_date) <= TO_DATE('10/29/2016', 'MM/DD/YYYY'))
GROUP BY E.EMPLOYEE_CATEGORY;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM