Oracle KEEP function Order By Keyword

Add a comment

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 :

WITH students AS
(
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 :

SELECT
    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 :

SELECT
    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 :

SELECT
    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.


Share and Enjoy:
  • Digg
  • del.icio.us
  • Google Bookmarks
  • Facebook
  • TwitThis
  • blogmarks
  • email
  • Furl
  • LinkedIn

This entry is filed under SQLing. And tagged with , , , . You can follow any responses to this entry through RSS 2.0. You can leave a response, or trackback from your own site.

  1. No Comments