Reputation: 5842
Below is my table structure , I am trying to get the UUID with status only as 'error' but no 'ok'.
I am doing something like this
select UUID from table where status='error'
MINUS
select UUID from table where status ='ok'
Is there a better way to doing this.
UUID | STATUS |
---|---|
3aa0a4ed-fa9f-472d-a208-8173288880ee | error |
3aa0a4ed-fa9f-472d-a208-8173288880ee | ok |
d7d76644-d8ce-4c5a-af42-6bc021fd264a | error |
d7d76644-d8ce-4c5a-af42-6bc021fd264a | ok |
082324d0-24a6-47ca-9b55-94fad628903e | error |
082324d0-24a6-47ca-9b55-94fad628903e | error |
3aa0a4ed-fa9f-472d-a208-8173288880ee | error |
3aa0a4ed-fa9f-472d-a208-8173288880ee | error |
Upvotes: 1
Views: 43
Reputation: 31
Best approach (in terms of performance) would be to use analytical function.
SELECT UUID FROM (
SELECT t.UUID UUID,
t.status status,
ROW_NUMBER () OVER (PARTITION BY UUID ORDER BY status DESC) status_rnk
FROM table t)
WHERE status = 'error' AND status_rnk = 1;
Upvotes: 1
Reputation: 6751
If you have only two statuses, you may use aggregation with one table scan:
select uuid from a group by uuid having min(status) = max(status) and min(status) = 'error'
| UUID | | :----------------------------------- | | 082324d0-24a6-47ca-9b55-94fad628903e |
Or with conditional aggregation that may be extended to more statuses:
select uuid from a group by uuid having count(decode(status, 'error', 1)) > 0 /*Has 'error' status*/ and count(nullif(status, 'error')) = 0 /*And has no other statuses*/
| UUID | | :----------------------------------- | | 082324d0-24a6-47ca-9b55-94fad628903e |
db<>fiddle here
Upvotes: 1
Reputation: 48780
You can use NOT EXISTS (<subquery>)
. For example:
select uuid
from my_table a
where status = 'error'
and not exists (
select 1 from my_table b where b.uuid = a.uuid and b.status = 'ok'
)
Or, you can use an anti-join:
select uuid
from my_table a
left join my_table b on b.uuid = a.uuid and b.status = 'ok'
where status = 'error'
and b.uuid is null
Upvotes: 1