Reputation: 576
I have three tables 1)fruits -- id, name 2)countries -- id, name 3)fruit_countries -- id, fruit_id(fk), country_id(fk)
In my fruits table I want to show fruits which are not present in a specific country on top.
I used
select
distinct(fruits.*),case when fruit_countries.country_id = xx then 1 else 0 end
from
"fruits"
left join fruit_countries on
fruit_countries.fruit_id = fruits.id
order by case when fruit_countries.country_id = xx then 1 else 0 end
the problem is since a fruit can be linked to multiple countries I get few fruits records on top of the list when they are present in country xx and some-other countries.
How can I fix this?
Upvotes: 0
Views: 48
Reputation: 23676
SELECT
*
FROM fruits f
LEFT JOIN fruit_countries fc ON f.id = fc.fruit_id
ORDER BY bool_or(fc.country_id = 1) OVER (PARTITION BY fc.fruit_id)
You can use the bool_or()
window function in the ORDER BY
clause. This checks if there is any records per fruit_id
group (partition) with the requested country_id
. If not, it will be ordered first.
However, the normal ORDER BY
orders the NULL
records to bottom. But, obviously they are not assigned to the specific country_id
as well (they are NULL
because there are assigned to no country), you could add NULLS FIRST
to the ORDER BY
clause, to order these fruits to top everytime.
Upvotes: 2
Reputation: 1077
If you are using rails 6.1 you can use
Fruit.where.missing(:countries) + Fruit.includes(:countries)
Upvotes: 0