Reputation: 201
I'm trying to create a user favorites system but having a difficult time creating a query that accomplishes what I need. I'll use fruits as an example.
First, here's my fruitsinfo
table:
id | color | rating
apples red 8.4
oranges orange 9.1
blueberries blue 8.8
pineapple yellow 7.9
peaches orange 8.3
Then there's the currentfruit
table, which lists only fruits that are in season and has their current market price (this data is hilariously bad, but bear with me):
id | price | months left in season
apples 1.25 6
avocados 1.42 4
pears 1.24 3
oranges 1.75 5
blueberries 2.20 4
Lastly, a userfavorites
table, which contains the userid and fruit id:
userid | fruitid
5 apples
5 peaches
5 pears
We'll just be working with the user with userid = '5'. A couple things to note here: not all the entries in currentfruits
are in fruitsinfo
and not all the entries in userfavorites
are in currentfruits
.
When the users usually access the site with no favorites saved, they just see currentfruits
left joined with fruitsinfo
and ordered by price, like so:
id | price | months left in season | color | rating
blueberries 2.20 4 blue 8.8
oranges 1.75 5 orange 9.1
avocados 1.42 4 null null
apples 1.25 6 red 8.4
pears 1.24 3 null null
Now, what I want is for there to be a check to see if any of user's favorite fruits are in the currentfruits
table, then list those results first (ordered by price), then the rest of the currentfruits (ordered by price). Our user has apples, pears, and peaches as favorites, but only apples and pears are in currentfruits, so the table should now look like:
id | price | months left in season | color | rating
apples 1.25 6 red 8.4
pears 1.24 3 null null
blueberries 2.20 4 blue 8.8
oranges 1.75 5 orange 9.1
avocados 1.42 4 null null
My initial thought was to do something like this:
SELECT *
FROM userfavorites
JOIN currentfruits ON userfavorites.fruitid = currentfruits.id
JOIN fruitsinfo ON currentfruits.id = fruitsinfo.id
ORDER BY currentfruits.price DESC
UNION
SELECT *
FROM currentfruits
LEFT JOIN fruitsinfo ON currentfruits.id = fruitsinfo.id
ORDER BY currentfruits.price DESC
The first SELECT
grabs the first two rows of the desired table and the second SELECT
grabs the entire table that a user would see without favorites. Unfortunately this didn't just slam the rows together like I hoped. Also because UNION only deals with distinct entries, I was hoping that would take care of the duplicate rows that might show up with the bottom select, but alas.
Can anyone tell me how I might go about making a query that accomplishes what I'm wanting to do? Thanks.
Upvotes: 1
Views: 839
Reputation:
You don't have to use a UNION. Try:
select c.id, c.price, c.`months left in season`, i.color, i.rating
from currentfruit c
left join fruitsinfo i on c.id = i.id
left join userfavorites f on c.id = f.id and f.userid = 5
order by case when f.id is not null then 0 else 1 end, c.price desc
Upvotes: 3