'Get Specific Data In a Table based on status
So i am having an issue regarding a query to get the latest data based on status
For example. I have a table like these
Schema (PostgreSQL v12)
CREATE TABLE test(
id INTEGER,
user_id INTEGER,
product VARCHAR(20),
status VARCHAR(20)
);
INSERT INTO test VALUES(1,1,'WALK','ACTIVE');
INSERT INTO test VALUES(2,1,'RUN','ACTIVE');
INSERT INTO test VALUES(3,2,'WALK','INACTIVE');
INSERT INTO test VALUES(4,2,'RUN','ACTIVE');
INSERT INTO test VALUES(5,3,'WALK','UPDATING');
INSERT INTO test VALUES(6,3,'RUN','ACTIVE');
INSERT INTO test VALUES(7,4,'WALK','UPDATING');
INSERT INTO test VALUES(8,4,'RUN','INACTIVE');
INSERT INTO test VALUES(9,2,'RUN','UPDATING');
Query #1
SELECT * FROM test;
| id | user_id | product | status |
|---|---|---|---|
| 1 | 1 | WALK | ACTIVE |
| 2 | 1 | RUN | ACTIVE |
| 3 | 2 | WALK | INACTIVE |
| 4 | 2 | RUN | ACTIVE |
| 5 | 3 | WALK | UPDATING |
| 6 | 3 | RUN | ACTIVE |
| 7 | 4 | WALK | UPDATING |
| 8 | 4 | RUN | INACTIVE |
| 9 | 2 | RUN | UPDATING |
Basically, i need a query to get the latest of user_id status and the status only for active and updating. But, if active and updating is exists, they pick the active one. So from this table, the result should be
| user_id | status |
|---|---|
| 1 | ACTIVE |
| 2 | ACTIVE |
| 3 | ACTIVE |
| 4 | UPDATING |
i tried this, but it only return the latest value
SELECT distinct on (user_id) user_id, status
FROM test
ORDER BY user_id DESC
Solution 1:[1]
Another option:
SELECT distinct on (user_id) user_id, status
FROM test
where status != 'INACTIVE'
ORDER BY user_id, array_position('{ACTIVE,UPDATING}', status)
When you do distinct on the order by is mandatory for the distinct field(s) (user_id in this case), but you also need to specify the sort criteria after that to determine which distinct record to show.
In other words, you want to only show one record by user id, but HOW do you determine which one? That's why you need the second argument in the order by.
Solution 2:[2]
using distinct on
SELECT distinct on (user_id) user_id, status
FROM test where status in ('ACTIVE','UPDATING')
ORDER BY user_id asc,id DESC
Solution 3:[3]
We can user ROW_NUMBER() in a CTE with ORDER BY id DESC so that number 1 is the latest row.
with cte as
(select
user_id,
status,
row_number() over (partition by user_id order by id desc) rn
from test
where status in ('ACTIVE','UPDATING')
)
select * from cte
where rn = 1
order by user_id;
| user_id | status | rn |
|---|---|---|
| 1 | ACTIVE | 1 |
| 2 | ACTIVE | 1 |
| 3 | ACTIVE | 1 |
| 4 | UPDATING | 1 |
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Zaynul Abadin Tuhin |
| Solution 3 |
