Reputation: 11
I am new to SQL and I am using MS SQL Server Management Studio 2014. I have 3 tables called Pizza, Pizza_Topping and Topping. I want to list the pizzas that have TOPPING1 and TOPPING2 as toppings. This is what I have came up with,
select Pizza.pizzaID, Pizza.pizzaName, Topping.toppingName
from Pizza left join Pizza_Topping on
Pizza.pizzaID = Pizza_Topping.pizzaID
left join Topping on
Topping.toppingID = Pizza_Topping.toppingID
where Topping.toppingName in ('topping1', 'topping2')
and this gives me
pizzaID pizzaName toppingName
-------- ---------------- --------------
PZ002 | PIZZA1 | TOPPING1
PZ002 | PIZZA1 | TOPPING2
PZ010 | PIZZA5 | TOPPING1
PZ010 | PIZZA5 | TOPPING2
PZ011 | PIZZA6 | TOPPING1
PZ012 | PIZZA7 | TOPPING2
I only need first four rows because last two pizzas only have one of the toppings not both. I have tried this as well,
GROUP BY Pizza.pizzaID,Pizza.pizzaName, Topping.toppingName HAVING COUNT(toppingName) >= 2
but it didn't give the expected result. that line can be used if I am going to display only pizzaID
and pizzaName
but i want to display toppingName
as well.
to be more clear, this what I am expecting
pizzaID pizzaName toppingName
-------- ---------------- --------------
PZ002 | PIZZA1 | TOPPING1
PZ002 | PIZZA1 | TOPPING2
PZ010 | PIZZA5 | TOPPING1
PZ010 | PIZZA5 | TOPPING2
Please tell me how to achieve this result. Thanks
Upvotes: 0
Views: 5028
Reputation: 197
You can solve this problem by using group by statement restricted to Pizza Id. Please refer below query.
select Pizza.pizzaID, Pizza.pizzaName, Pizza_Toppings.Remark
from Pizza join Pizza_Toppings on
Pizza.pizzaID = Pizza_Toppings.pizzaID
join Toppings on
Toppings.toppingID = Pizza_Toppings.toppingID
where Pizza.PizzaId in (
select Pizza.PizzaID
from Pizza join Pizza_Toppings on
Pizza.pizzaID = Pizza_Toppings.pizzaID
join Toppings on
Toppings.toppingID = Pizza_Toppings.toppingID
where Toppings.TopingName in ('topping1', 'topping2')
group by pizza.PizzaId
having count(Pizza.PizzaId ) > 1)
Please let me know if this does not work for you.
Upvotes: 0
Reputation: 20794
You have to join to the pizza_topping and topping tables twice.
select yourfields
from pizza join pizza_topping pt1 on pizza.pizzaID = pt1.pizzaID
join topping t1 on pt1.toppingID = t1.toppingId
join pizza_topping pt2 on pizza.pizzaID = pt2.pizzaID
join topping t2 on pt2.toppingID = t2.toppingId
where t1.toppingName = 'topping1'
and t2.toppingName = 'topping2'
Upvotes: 0
Reputation: 60462
To include the toppings you can do the COUNT-logic using Windowed Aggregate Functions:
SELECT p.pizzaID, p.pizzaName, dt.toppingName
FROM Pizza AS p
JOIN
(
SELECT p.pizzaID, t.toppingName,
COUNT(*) OVER (PARTITION BY p.pizzaID) AS cnt -- number of matching toppings
FROM Pizza_Topping AS pt
JOIN Topping AS t
ON t.toppingID = pt.toppingID
WHERE t.toppingName IN ('topping1', 'topping2')
) AS dt
ON p.pizzaID = dt.pizzaID
WHERE cnt = 2 -- number of searched toppings
Upvotes: 0
Reputation: 13713
I think this could be done more easily if you can get the count()
in your subquery and then join back all the pizzaid's that have count greater than 1 something like this:
SELECT q1.pizzaID
,q1.PizzaName
,t.ToppingName
FROM (
SELECT Pizza.pizzaID
,Pizza.pizzaName
,count(topping.ToppingName) total_count
FROM Pizza
INNER JOIN Pizza_Topping ON Pizza.pizzaID = Pizza_Topping.pizzaID
INNER JOIN Topping ON Topping.toppingID = Pizza_Topping.toppingID
GROUP BY Pizza.pizzaID
,Pizza.pizzaName
HAVING count(topping.ToppingName) > 1
) q1
INNER JOIN Pizza_Topping pt ON q1.pizzaID = pt.pizzaID
INNER JOIN Topping t ON t.toppingID = pt.toppingID
WHERE t.toppingName in ('topping1', 'topping2')
Upvotes: 0
Reputation: 1581
Get your result without topping name . Wrap it in a view and do an inner join with Topping table .
Upvotes: 0
Reputation: 1269445
You are almost correct. You need to remove ToppingName
from the GROUP BY
:
GROUP BY Pizza.pizzaID, Pizza.pizzaName
HAVING COUNT(toppingName) >= 2
You also need to remove it from the SELECT
if it is also there:
select p.pizzaID, p.pizzaName
from Pizza p join
Pizza_Topping pt
on p.pizzaID = pt.pizzaID join
Topping t
ont.toppingID = pt.toppingID
where t.toppingName in ('topping1', 'topping2')
group by p.pizzaID, p.pizzaName
having count(*) >= 2;
Also notice two things. Because you have a condition on toppings, the left join
is unnecessary. You are only looking for matches, so inner join
is appropriate. The use of table aliases makes the query easier to write and to read.
This assumes that pizzas cannot have duplicate toppings. If so, then change the last condition to:
having count(distinct t.toppingName) >= 2
Upvotes: 1