I’m working on a restaurant CMS app. I have a many-to-many relationship between 2 tables, menu_sections and menu_items. The relationship is maintained with a table in between called menu_relationships.
As an example let’s say the menu section called Snacks (menu_section_id = 1) contains a menu item called Pretzels (menu_item_id = 1) and the menu section called Desserts (menu_section_id = 2) contains a menu item called Ice Cream (menu_item_id = 2), but Ice Cream is also contained within another menu section called Kids Food (menu_section_id = 3). So there would be 3 rows in the menu_relationships table to map out these 3 relationships. The relationship table would look like this:
---------------------------------------
| menu_section_id | menu_item_id |
|=====================================|
| 1 | 1 |
|-------------------------------------|
| 2 | 2 |
|-------------------------------------|
| 3 | 2 |
---------------------------------------
So far so good.
I want to generate a result set that will return the names of all menu items except for menu items with a given menu_section_id. So to return the menu item names, I have a join on the menu_items table. Here’s the SQL:
SELECT menu_section_id, menu_items.menu_item_id, menu_item_name
FROM menu_relationships
JOIN menu_items
ON menu_items.menu_item_id = menu_relationships.menu_item_id
WHERE menu_section_id != 2
The result set which will give me a row for each relationship that doesn’t contain a given menu_section_id. With the example data I would be getting 2 rows back from the relationship table:
-----------------------------------------------------------
| menu_section_id | menu_item_id | menu_item_name |
|======================================|==================|
| 1 | 1 | Pretzels |
|--------------------------------------|------------------|
| 3 | 2 | Ice Cream |
-----------------------------------------------------------
But what I want is to exclude the menu item altogether from the result set, if it has ANY relationship to the specified menu_section_id. In other words, in the case of this example , I only want to return rows for menu items that have no relationship mappings at all to a menu_section_id of 2, I only want to return the Pretzels row.
I’ve tried various things with GROUP BY and HAVING using the bit_xor() aggregate function, but so far no luck at all in getting what I want.
I probably could have taken less time to explain that but I wanted it to be a clear as I can make it. I hope it is. Can anyone help?
There are many ways to do this. Here is one example using
WHERE ... NOT IN (...):