Oracle SQL - Help using Case in a Select Statement
CREATE TABLE student_totalexp2 nologging compress AS
SELECT /*+parallel(a,4)*/ DISTINCT a.member_sk,
CASE
WHEN b.end_date IS NULL THEN
SYSDATE - MIN(TO_DATE(b.start_date,'yyyymm'))
ELSE
(MAX(TO_DATE(b.end_date,'yyyymm')) - MIN(TO_DATE(b.start_date,'yyyymm')))
END as days_experience
FROM student_schools a
JOIN rdorwart.position_rd b ON a.member_sk = b.member_sk
WHERE days_experience < 730
GROUP BY a.member_sk;
SELECT COUNT(*)
FROM student_experience;
Any idea why I keep getting this error: Error 开发者_开发百科report:
SQL Error: ORA-00904: "DAYS_EXPERIENCE": invalid identifier 00904. 00000 - "%s: invalid identifier" *Cause:
*Action:
You cannot reference a alias in the WHERE
clause. Either use a subquery, or better just the entire CASE...END
into your where clause.
Updated query per OP's comments:
create table student_totalexp2 nologging compress as
SELECT a.member_sk,
SUM(CASE WHEN b.end_date IS NULL
THEN sysdate
ELSE to_date(b.end_date,'yyyymm')
END - to_date(b.start_date,'yyyymm')) as days_experience
FROM student_schools a INNER JOIN rdorwart.position_rd b
ON a.member_sk = b.member_sk
GROUP BY a.member_sk
HAVING SUM(
CASE WHEN b.end_date IS NULL
THEN sysdate
ELSE to_date(b.end_date,'yyyymm')
END - to_date(b.start_date,'yyyymm')
) < 730;
SELECT COUNT(*) FROM student_experience;
The below is a direct simplification of the query in the question, taking MAX (any row) against MIN (any row). The Scrum Meister's answer fixes the OP's logic as well, to correctly cater for gaps between jobs.
This should be all you need. Having the student_schools table JOINed seems to add no value, unless there are cases where position_rd records exist without a
student_schools
record.
CREATE TABLE student_totalexp2 nologging compress AS
SELECT b.member_sk,
NVL(MAX(TO_DATE(b.end_date,'yyyymm')), SYSDATE)
- MIN(TO_DATE(b.start_date,'yyyymm')) as days_experience
FROM rdorwart.position_rd b
GROUP BY b.member_sk
HAVING NVL(MAX(TO_DATE(b.end_date,'yyyymm')), SYSDATE)
- MIN(TO_DATE(b.start_date,'yyyymm')) < 730
- The NVL takes care of replacing a non-existent end_date with SYSDATE
If you do need to validate student_schools
- just add an INNER JOIN to it. Nowhere else is it needed.
you cannot use guiven name of the field directly in where clause. You need to repeat the logic in where clause
select /*+parallel(a,4)*/ distinct a.member_sk,
CASE WHEN b.end_date is null
THEN sysdate - min(to_date(b.start_date,'yyyymm'))
ELSE (max(to_date(b.end_date,'yyyymm')) - min(to_date(b.start_date,'yyyymm')))
END as days_experience
from student_schools a INNER JOIN rdorwart.position_rd b
ON a.member_sk = b.member_sk
where (CASE WHEN b.end_date is null
THEN sysdate - min(to_date(b.start_date,'yyyymm'))
ELSE (max(to_date(b.end_date,'yyyymm')) - min(to_date(b.start_date,'yyyymm')))
END) < 730
group by a.member_sk;
select count(*) from student_experience;
For short and more readable code, use an outer SELECT:
CREATE TABLE student_totalexp2 nologging compress AS
SELECT member_sk, days_experience FROM (
SELECT a.member_sk
, SUM(CASE WHEN b.end_date IS NULL
THEN sysdate ELSE to_date(b.end_date,'yyyymm') END
- to_date(b.start_date,'yyyymm')) AS days_experience
FROM student_schools a
INNER JOIN rdorwart.position_rd b ON a.member_sk = b.member_sk
GROUP BY a.member_sk)
WHERE days_experience < 730;
SELECT COUNT(*)
FROM student_experience;
精彩评论