hopefully someone has an idea for a more performant Oracle SQL.
Following Oracle PERSON-Table:
ID | PERSON_ID | REFERENCE_ID | COMMENT | CREATION_DATE |
---|---|---|---|---|
1 | 10066 | 666 | comment 2 days ago | 01-11-2022 09:16:00.00000 |
2 | 10066 | 111 | single comment | 01-11-2022 11:44:00.00000 |
3 | 10066 | 666 | comment 1 day ago | 02-11-2022 07:37:00.00000 |
4 | 33444 | 666 | comment of different person | 02-11-2022 09:54:00.00000 |
5 | 10066 | 666 | comment today | 03-11-2022 08:46:00.00000 |
6 | 10066 | 987 | another comment | 03-11-2022 09:02:00.00000 |
7 | 10066 | 987 | another comment same day | 03-11-2022 09:44:22.123456 |
I want to have only the recent timestamps of identical REFERENCE_ID results from a specific PERSON_ID.
So I expect 3 rows should be in the result list for PERSON_ID 10066:
PERSON_ID | REFERENCE_ID | COMMENT | CREATION_DATE |
---|---|---|---|
10066 | 111 | single comment | 01-11-2022 11:44:00.00000 |
10066 | 666 | comment today | 03-11-2022 08:46:00.00000 |
10066 | 987 | another comment same day | 03-11-2022 09:44:22.123456 |
I came up with a subselect idea which works, but is possibly not the best / most performant solution:
SELECT * FROM PERSON_TABLE p WHERE CREATION_DATE = (
SELECT MAX(CREATION_DATE)
FROM PERSON_TABLE
WHERE REFERENCE_ID = p.REFERENCE_ID AND PERSON_ID = 10066
);
Has someone a better idea? Or is my approach ok performance wise? I have the feeling there are more optimized statements / queries possible, maybe without subselect.
Thanks in advance, have a nice day!
CodePudding user response:
If I am understanding the question correctly I think a DISTINCT
clause may achieve the same results.
Something like select distinct REFERENCE_ID, PERSON_ID, COMMENT, CREATION_DATE from PERSON_TABLE order by REFERENCE_ID desc
.
CodePudding user response:
One option is to rank rows per each person and reference, and then fetch the ones that rank as the highest.
Sample data:
SQL> with person (id, person_id, reference_id, creation_date) as
2 (select 1, 1066, 666, to_date('01.11.2022 09:16', 'dd.mm.yyyy hh24:mi') from dual union all
3 select 2, 1066, 111, to_date('01.11.2022 11:44', 'dd.mm.yyyy hh24:mi') from dual union all
4 select 3, 1066, 666, to_date('02.11.2022 07:37', 'dd.mm.yyyy hh24:mi') from dual union all
5 select 5, 1066, 666, to_date('03.11.2022 08:46', 'dd.mm.yyyy hh24:mi') from dual union all
6 select 6, 1066, 987, to_date('03.11.2022 09:02', 'dd.mm.yyyy hh24:mi') from dual union all
7 select 7, 1066, 987, to_date('03.11.2022 09:44', 'dd.mm.yyyy hh24:mi') from dual
8 ),
Query begins here:
9 temp as
10 (select p.*,
11 row_number() over (partition by person_id, reference_id order by creation_date desc) rn
12 from person p
13 )
14 select id, person_id, reference_id, creation_date
15 from temp
16 where person_id = 1066
17 and rn = 1;
ID PERSON_ID REFERENCE_ID CREATION
---------- ---------- ------------ --------
2 1066 111 01.11.22
5 1066 666 03.11.22
7 1066 987 03.11.22
SQL>