Reputation: 2110
Imagine I have two tables, food
and people
, and I indicate who likes which food with a link table. So:
foods
-----
sausages
pie
Mars bar
people
------
john
paul
george
ringo
person | food (link table)
-------+-----
john | pie
john | sausage
paul | sausage
I'd like to get a list of foods, along with a person who likes that food. So I'd like a table like this:
food | a randomly chosen liker
---------+------------------------
sausage | john (note: this could be "paul" instead)
pie | john (note: must be john; he's the only liker)
Mars bar | null (note: nobody likes it)
Is it possible to do this in one query?
Obviously, I can do:
select
f.food, p.person
from
food f inner join link l
on f.food = l.food
inner join person p
on l.person = p.person
but that will give me two sausage
rows, because two people like it, and I'll have to deduplicate the rows myself.
Upvotes: 1
Views: 86
Reputation: 6672
Another variant.. (Assuming it is SQL Server )
Select
a.Food, b.Person
from
foods a
outer apply
(
Select top 1 Person from linkTable b where a.Food = b.Food
) b
Upvotes: 0
Reputation: 44766
Do LEFT JOINs
to also get food that no-one likes. GROUP BY
to get each food only once, use MIN
to pick first person that likes that food.
select f.food, min(p.person)
from food f
left join linktable l on f.id = l.food_id
left join people p on p.id = l.person_id
group by f.food
Upvotes: 1
Reputation: 1709
I would use a partition to do that, example:
WITH ORDERED AS
(
SELECT
PERSON,
FOOD,
ROW_NUMBER() OVER (PARTITION BY lower(FOOD) ORDER BY lower(PERSON) DESC) AS RN
FROM
(
SELECT 'john' AS PERSON ,'pie' AS FOOD FROM DUAL UNION
SELECT 'john1' AS PERSON ,'sausage' AS FOOD FROM DUAL UNION
SELECT 'john2' AS PERSON ,'sausage' AS FOOD FROM DUAL UNION
SELECT 'john3' AS PERSON ,'sausage' AS FOOD FROM DUAL UNION
SELECT 'john4' AS PERSON ,'sausage' AS FOOD FROM DUAL UNION
SELECT 'john5' AS PERSON ,'eggs' AS FOOD FROM DUAL UNION
SELECT 'john6' AS PERSON ,'sausage' AS FOOD FROM DUAL UNION
SELECT 'dada' AS PERSON ,'sausage' AS FOOD FROM DUAL UNION
SELECT 'paul' AS PERSON ,'sausage' AS FOOD FROM DUAL
-- Your select statement here that links the two tables
) PERSON_FOOD
)
SELECT
FOOD,
PERSON
FROM
ORDERED
WHERE
RN = 1
This will get you the following:
FOOD | PERSON
-------------------
eggs | john
pie | john
sausage | paul
This is in oracle syntax
Upvotes: 0
Reputation: 2058
select f.food, min(l.person)
from food f
left join link l on f.foods = l.food
group by f.food
Upvotes: 0