Reputation: 1150
I am attempting to query an oracle db but cant quite get the script to work. The script is meant to search for employees with a start_date
between two dates. Unfortunately, not all employees have a start_date
in the database, but all employees have a 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!
Thanks in advance!
Upvotes: 1
Views: 100
Reputation: 2686
Use nvl 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 ((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;
Upvotes: 0
Reputation: 1269503
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.
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. The time to use case
is when you explicitly want to sequence the conditions, particularly when one condition might be an expensive function call.
Upvotes: 2