I ran into a problem and maybe there are experienced guys here to help me figure it out: I have a table with rows:
ID | VALUE | DATE |
---|---|---|
2827 | 0 | 20.07.2022 10:40:01 |
490 | 27432 | 20.07.2022 10:40:01 |
565 | 189 | 20.07.2022 9:51:03 |
200 | 1 | 20.07.2022 9:50:01 |
731 | 0.91 | 20.07.2022 9:43:21 |
161 | 13004 | 19.07.2022 16:11:01 |
This table has a million records, there are about 1000 ID instances, only the date of the value change and, therefore, the value itself changes in them. When the value of the ID changes is added to this table:
ID | Tme the value was changed (DATE) | VALUE
My task is to get the all id's values closest to the input date.
I mean: if I input date "20.07.2022 10:00:00" I want to get each ID (1-1000) with rows "value, date" with last date before "20.07.2022 10:00:00":
ID | VALUE | DATE |
---|---|---|
2827 | 0 | 20.07.2022 9:59:11 |
490 | 27432 | 20.07.2022 9:40:01 |
565 | 189 | 20.07.2022 9:51:03 |
200 | 1 | 20.07.2022 9:50:01 |
731 | 0.91 | 20.07.2022 8:43:21 |
161 | 13004 | 19.07.2022 16:11:01 |
What query will be the most optimal and correct in this case?
CodePudding user response:
If you want the data for each ID with the latest change up to, but not after, your input date then you can just filter on that date, and use aggregate functions to get the most recent data in that filtered range:
select id,
max(change_time) as change_time,
max(value) keep (dense_rank last order by change_time) as value
from your_table
where change_time <= <your input date>
group by id
With your previous sample data, using midnight this morning as the input date would give:
select id,
max(change_time) as change_time,
max(value) keep (dense_rank last order by change_time) as value
from your_table
where change_time <= timestamp '2022-07-28 00:00:00'
group by id
order by id
ID | CHANGE_TIME | VALUE |
---|---|---|
1 | 2022-07-24 10:00:00 | 900 |
2 | 2022-07-22 21:51:00 | 422 |
3 | 2022-07-24 13:01:00 | 1 |
4 | 2022-07-24 10:48:00 | 67 |
and using midday today woudl give:
select id,
max(change_time) as change_time,
max(value) keep (dense_rank last order by change_time) as value
from your_table
where change_time <= timestamp '2022-07-28 12:00:00'
group by id
order by id
ID | CHANGE_TIME | VALUE |
---|---|---|
1 | 2022-07-24 10:00:00 | 900 |
2 | 2022-07-22 21:51:00 | 422 |
3 | 2022-07-28 11:59:00 | 12 |
4 | 2022-07-28 11:45:00 | 63 |
5 | 2022-07-28 10:20:00 | 55 |
db<>fiddle with some other input dates to show the result set changing.