2

I have a table where first I need to select data by max(event_date) then need to filter the data by max(event_sequence) then filter again by max(event_number)

I wrote following query which works but takes time.

Here the the query

SELECT DISTINCT a.stuid,
                   a.prog,
                   a.stu_prog_id,
                   a.event_number,
                   a.event_date,
                   a.event_sequence,
                   a.prog_status
   FROM table1 a
   WHERE a.event_date=
       (SELECT max(b.event_date)
        FROM table1 b
        WHERE a.stuid=b.stuid
          AND a.prog=b.prog
          AND a.stu_prog_id=b.stu_prog_id)
     AND a.event_seq=
       (SELECT max(b.event_sequence)
        FROM table1 b
        WHERE a.stuid=b.stuid
          AND a.prog=b.prog
          AND a.stu_prog_id=b.stu_prog_id
          AND a.event_date=b.event_date)
     AND a.event_number=
       (SELECT max(b.event_number)
        FROM table1 b
        WHERE a.stuid=b.stuid
          AND a.prog=b.prog
          AND a.stu_prog_id=b.stu_prog_id
          AND a.event_date=b.event_date
          AND a.event_sequence=b.event_sequence

I was wondering is there there a faster way to get the data? I am using Oracle 12c.

4 Answers 4

2

You could try rephrasing your query using analytic functions:

SELECT
    stuid,
    prog,
    stu_prog_id,
    event_number,
    event_date,
    event_sequence,
    prog_status
FROM
(
    SELECT t.*,
        RANK() OVER (PARTITION BY studio, prog, stu_prog_id
                     ORDER BY event_date DESC) rnk1,
        RANK() OVER (PARTITION BY studio, prog, stu_prog_id, event_date
                     ORDER BY event_sequence DESC) rnk2,
        RANK() OVER (PARTITION BY studio, prog, stu_prog_id, event_date, event_sequence
                     ORDER BY event_number DESC) rnk3
    FROM table1 t
) t
WHERE rnk1 = 1 AND rnk2 = 1 AND rnk3 = 1;

Note: I don't actually know if you really need all three subqueries there. Adding sample data to your question might help someone else improve upon the solution I have given above.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for reply. I tried this query but it does not work as expected(exclude some prog). I will try to upload the data.
1

I think you want a simple row_number() or rank():

select t1.*
from (select t1.*,
             rank() over (partition by stuid, prog, stu_prog_id
                          order by event_date desc, event_sequence desc, event_number desc
                         ) as seqnum
      from table1 t1
     ) t1
where seqnum = 1;

1 Comment

It works:) I could not up vote you as I have less than 15 reputation.
0

If you have multiple records with EVENT_DATE, EVENT_SEQUENCE, EVENT_NUMBER as max respectively then in Tim's solution, Use DENSE_RANK or use the following to fetch the exact max and compare with original column data.

SELECT DISTINCT
    A.STUID,
    A.PROG,
    A.STU_PROG_ID,
    A.EVENT_NUMBER,
    A.EVENT_DATE,
    A.EVENT_SEQUENCE,
    A.PROG_STATUS
FROM
    (
        SELECT
            A.STUID,
            A.PROG,
            A.STU_PROG_ID,
            A.EVENT_NUMBER,
            A.EVENT_DATE,
            A.EVENT_SEQUENCE,
            A.PROG_STATUS,
            MAX(A.EVENT_DATE) OVER(
                PARTITION BY A.STUID, A.PROG, A.STU_PROG_ID
            ) AS MAX_EVENT_DATE,
            MAX(A.EVENT_SEQUENCE) OVER(
                PARTITION BY A.STUID, A.PROG, A.STU_PROG_ID, A.EVENT_DATE
            ) AS MAX_EVENT_SEQUENCE,
            MAX(A.EVENT_NUMBER) OVER(
                PARTITION BY A.STUID, A.PROG, A.STU_PROG_ID, A.EVENT_DATE, A.EVENT_SEQUENCE
            ) AS MAX_EVENT_NUMBER
        FROM
            TABLE1 A
    ) A
WHERE
    A.MAX_EVENT_DATE = A.EVENT_DATE
    AND A.MAX_EVENT_SEQUENCE = A.EVENT_SEQUENCE
    AND A.MAX_EVENT_NUMBER = A.EVENT_NUMBER;

Cheers!!

Comments

0

As being an Oracle 12c user, you can use

[ OFFSET offset { ROW | ROWS } ]
[ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ]
    { ROW | ROWS } { ONLY | WITH TIES } ]

syntax as :

SELECT DISTINCT a.stuid,
                a.prog,
                a.stu_prog_id,
                a.event_number,
                a.event_date,
                a.event_sequence,
                a.prog_status
  FROM table1 a
 ORDER BY event_date DESC, event_sequence DESC, event_number DESC
 FETCH FIRST 1 ROW ONLY;

where WITH TIES clause is not needed for your case, since you're looking for DISTINCT rows, and OFFSET is not needed either, since starting point is just the beginning of a descendingly ordered columns. Even, using the keyword ROW as ROWS is optional, even for the case of plural rows such as FETCH FIRST 5 ROW ONLY; ^^ --> ROWS without S

Demo

3 Comments

I think this will return only one row or number of rows but not first row from each group.
@Tejash No, there's no problem per each group, since each column is restricted among each other step by step. Consider this. event_sequence is filtered by event_date, and event_number is filtered by event_date and event_sequence.
There will be max event date for each stuid, prog and stu_prog_id.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.