Oracle KEEP function Order By Keyword
I found something funny with the Oracle Keep / { First - Last } analytic function, on 11.0.0.6 & 11.0.0.7.
Same thing occurs also on Oracle 10g XE.
For those who don't have a clue about this function, I wrote a small post on this subject.
Let's use the same query :
(
SELECT 1 AS stud_id, 'JAMES' AS name, date '1989-07-14' AS birthdate FROM dual union ALL
SELECT 2, 'JOHN' , date '1991-02-07' FROM dual union ALL
SELECT 3, 'ROBERT' , date '1986-08-23' FROM dual union ALL
SELECT 4, 'MICHAEL', date '1983-12-02' FROM dual union ALL
SELECT 5, 'WILLIAM', date '1988-03-02' FROM dual union ALL
SELECT 6, 'DAVID' , date '1984-05-12' FROM dual union ALL
SELECT 7, 'RICHARD', date '1984-06-06' FROM dual union ALL
SELECT 8, 'CHARLES', date '1984-09-07' FROM dual
),
course AS
(
SELECT 1 AS cour_id, 1 AS stud_id FROM dual union ALL
SELECT 2, 2 FROM dual union ALL
SELECT 1, 3 FROM dual union ALL
SELECT 3, 4 FROM dual union ALL
SELECT 2, 5 FROM dual union ALL
SELECT 2, 6 FROM dual union ALL
SELECT 1, 7 FROM dual union ALL
SELECT 1, 8 FROM dual
)
SELECT
co.cour_id,
max(st.name) keep (dense_rank last sdfklgjkldfgjkldf BY st.birthdate ASC) AS youngest,
max(st.name) keep (dense_rank first ORDER BY st.birthdate ASC) AS oldest
FROM
students st
INNER JOIN course co
ON co.stud_id = st.stud_id
GROUP BY
co.cour_id
ORDER BY
co.cour_id ASC;
COUR_ID YOUNGEST OLDEST
---------- ----------- -----------
1 JAMES RICHARD
2 JOHN DAVID
3 MICHAEL MICHAEL
I was wondering if I could do some complex aggregate using the partition keyword :
co.cour_id,
max(st.name) keep (dense_rank last partition BY co.cour_id) AS test --order by count(*) desc) AS test
FROM
students st
INNER JOIN course co
ON co.stud_id = st.stud_id
GROUP BY
co.cour_id
ORDER BY
co.cour_id ASC
Well, the answer is no, the result is wrong.
But The SQL wasn't rejected... I was wondering why and found out :
co.cour_id,
max(st.name) keep (dense_rank last ORDER BY birthdate DESC) AS test1,
max(st.name) keep (dense_rank last partition BY birthdate DESC) AS test2,
max(st.name) keep (dense_rank last this BY birthdate DESC) AS test3,
max(st.name) keep (dense_rank last IS BY birthdate DESC) AS test4,
max(st.name) keep (dense_rank last strange BY birthdate DESC) AS test5,
max(st.name) keep (dense_rank last BY BY birthdate DESC) AS test6,
max(st.name) keep (dense_rank last BYE BY birthdate DESC) AS test7
FROM
students st
INNER JOIN course co
ON co.stud_id = st.stud_id
GROUP BY
co.cour_id
ORDER BY
co.cour_id ASC
You can write whatever you want !
But you still have to write something :
co.cour_id,
max(st.name) keep (dense_rank last BY birthdate DESC) AS test
FROM
students st
INNER JOIN course co
ON co.stud_id = st.stud_id
GROUP BY
co.cour_id
ORDER BY
co.cour_id ASC;
ORA-00924 : missing BY keyword
Cause: The keyword BY was omitted IN a GROUP BY, ORDER BY, OR CONNECT BY clause.
IN a GRANT statement, the keyword IDENTIFIED must also be followed BY the keyword BY.
Action: Correct the syntax.
INSERT the keyword BY WHERE required AND then retry the statement.
Well, it's not the right error but it's at least an error.
I suppose that for avoiding database upgrade trouble you should stick to ORDER BY.
This entry is filed under SQLing. And tagged with keep, Oracle, order by, SQL. You can follow any responses to this entry through RSS 2.0. You can leave a response, or trackback from your own site.