Reputation: 1
I have a SQL table with monthly records at the ID level. I'm interested in isolating only IDs whose VALUE has changed between the earliest month (July) and the latest (September).
| ID_FIELD | MONTH | VALUE |
|:-----------|------------:|:------------:|
| ID1 | 01-JUL-20 | 3 |
| ID1 | 01-AUG-20 | 3 |
| ID1 | 01-SEP-20 | 3 |
| ID2 | 01-JUL-20 | 2 |
| ID2 | 01-AUG-20 | 2 |
| ID2 | 01-SEP-20 | 3 |
| ID3 | 01-JUL-20 | 1 |
| ID3 | 01-AUG-20 | 3 |
| ID3 | 01-SEP-20 | 3 |
Seems simple - but not sure the easiest way to tackle this. I'm using Oracle SQL Developer. Thanks!
Upvotes: 0
Views: 36
Reputation: 2336
Gordon has given you a correct answer if you care about any changes whatsoever, but I'm interpreting your question differently - you only care about the id_field values if their value for their earliest month is different to their most recent, ignoring those that have had a value in between those two months.
First you want the earliest and most recent values:
select *
from (
select id_field, value, row_number() over (partition by id_field order by month) rn_asc, row_number() over (partition by id_field order by month desc) rn_desc
from my_table
)
where 1 in (rn_asc, rn_desc)
You could then apply a having condition
select id_field
from (
select id_field, value, row_number() over (partition by id_field order by month) rn_asc, row_number() over (partition by id_field order by month desc) rn_desc
from my_table
)
where 1 in (rn_asc, rn_desc)
group by id_field
having count(distinct value) > 1
Or you could use a set operator like:
with sorted_table as
(select id_field, value, row_number() over (partition by id_field order by month) rn_asc, row_number() over (partition by id_field order by month desc) rn_desc
from my_table
)
select distinct id_field
from (select id_field, value
from sorted_table
where rn_asc = 1
minus
select id_field, value
from sorted_table
where rn_desc = 1
)
Both options assume you only have a row per id_field per month value.
Upvotes: 1
Reputation: 1270643
If you want a change then you are looking for different values. So:
select id_field
from t
group by id_field
having min(value) <> max(value);
Upvotes: 2