Reputation: 772
So I have a union of various queries representing various conditions in order to reach my end goal, which is a list of entries according to their priority. This priority is given according to the
My query is
select priority, priority_description, name_of_entry, id_of_entry from (
select 0 priority, 'text' priority_description, name_of_entry, id_of_entry from table_a where *conditions for priority 0*
union select 1 priority, 'text' priority_description, name_of_entry, id_of_entry from table_a where *conditions for priority 1*
union select 2 priority, 'text' priority_description, name_of_entry, id_of_entry from table_a, tableb where *conditions for priority 2*
union select 3 priority, 'text' priority_description, name_of_entry, id_of_entry from table_a, tablec where *conditions for priority 3*
) x
The numbers and text for 1st and 2nd columns are manually entered while the others are what I want to retrieve.
The intended result is to only show the entry with the least priority if it's replicated. In other words, if an entry fulfils multiple conditions, thus appearing in priority 2 and 3, I only want the record to be shown once with priority 2.
One idea would be for example to add another condition "and where not exists in (previous condition), however this might make everything way too slow since it would be repeating queries multiple times.
How to achieve this in a better way?
Upvotes: 0
Views: 73
Reputation: 3823
Here's another option:
SELECT priority, priority_description, name_of_entry, id_of_entry
FROM (
SELECT priority, priority_description, name_of_entry, id_of_entry,
ROW_NUMBER() OVER(
PARTITION BY id_of_entry -- Group rows by "id_of_entry"
ORDER BY priority -- Assign "ranking" based on lowest priority
) AS RowNum
FROM (
SELECT
CASE
WHEN <conditions for priority 0> THEN 0 -- Look for priority 0 first
WHEN <conditions for priority 1> THEN 1
WHEN <conditions for priority 2> THEN 2
WHEN <conditions for priority 3> THEN 3
END AS priority,
'text' AS priority_description,
name_of_entry,
id_of_entry
FROM table_a
) src
) src
WHERE RowNum = 1 -- Get single rows with lowest priority
This assumes the same id_of_entry
value can have multiple rows with different priority
conditions.
Also, how do you handle cases when there are multiple rows with the same id_of_entry
and priority
values? As written, the query won't discriminate with regards to which row to return.
Upvotes: 1
Reputation: 44230
You only select from table_a, with conditions on table[abc],so you can rewrite into:
SELECT COALESCE(zero.priority,one.priority,two.priority,three.priority)
AS priority
, a.name_of_entry, a.id_of_entry
, ...
FROM table_a a
LEFT JOIN (
select 0 priority, id_of_entry
from table_a
where *conditions for priority 0*
) zero ON zero.id_of_entry = a.id_of_entry
LEFT JOIN (
select 1 priority, id_of_entry
from table_a
where *conditions for priority 1*
) one ON one.id_of_entry = a.id_of_entry
LEFT JOIN (
select 2 priority, id_of_entry
from table_a
WHERE EXISTS(
SELECT*FROM table_b WHERE [table_a,table_b]
AND *conditions for priority 2*)
) two ON two.id_of_entry = a.id_of_entry
LEFT JOIN (
select 3 priority, id_of_entry
from table_a
WHERE EXISTS(
SELECT*FROM table_c WHERE [table_a,table_c]
AND *conditions for priority 3*)
) three ON three.id_of_entry = a.id_of_entry
;
Upvotes: 0
Reputation: 1269493
You can use distinct on
:
with q as (<your query here>)
select distinct on (id_entry) q.*
from q
order by id_entry, priority;
That said, you can probably just use a single case
expression for this. It is a little complicated because you have two values. One method is something like this:
select v.priority,
(case when v.priority = 0 then 'text0'
when v.priority = 1 then 'text1'
when v.priority = 2 then 'text2'
when v.priority = 3 then 'text3'
end) as priority_description,
name_of_entry, id_of_entry
from table_a a cross join lateral
(values (case when *conditions for priority 0* then 0
when *conditions for priority 1* then 1
when *conditions for priority 2* then 2
when *conditions for priority 3* then 3
end)
) v(priority)
You can add in the
Upvotes: 1