Reputation: 47
I have three tables (Users, Items, UserItems) where UserItems is a many-to-many relationship between Users and Items. What I need is a query that gets all Items that a User does not have.
I've created a SQL Fiddle example with some fake data here: http://sqlfiddle.com/#!6/a6856/1
CREATE TABLE Users ( userID INT, firstName NVARCHAR(50) )
CREATE TABLE Items ( itemID INT, itemName NVARCHAR(50) )
CREATE TABLE UserItems ( userID INT, itemID INT )
INSERT INTO Users ( userID, firstName )
VALUES ( 1, 'Jack' ), ( 2, 'Jill' ), ( 3, 'John' ), ( 4, 'Jane' );
INSERT INTO Items ( itemID, itemName )
VALUES ( 1, 'Bucket' ), ( 2, 'Water' ), ( 3, 'Cast' );
INSERT INTO UserItems ( userID, itemID )
VALUES ( 1, 1 ), ( 1, 2 ), ( 1, 3 ), ( 2, 3 );
Desired Results Users and what items they DO NOT have:
---------------------------------
| userID | firstName | itemName |
|--------|-----------|----------|
| 2 | Jill | Bucket |
| 2 | Jill | Water |
| 3 | John | Bucket |
| 3 | John | Water |
| 3 | John | Cast |
| 4 | Jane | Bucket |
| 4 | Jane | Water |
| 4 | Jane | Cast |
---------------------------------
NOTE: Jack does not need to be in the results because he has all three items.
Upvotes: 0
Views: 1404
Reputation: 56
NOT EXISTS
seems like a perfect fit here
SELECT
usr.userID
, usr.firstName
, itm.itemName
FROM
Users usr
, Items itm
WHERE NOT EXISTS
(
SELECT *
FROM UserItems usrItm
WHERE
usrItm.itemID = itm.itemID
AND usrItm.userID = usr.userID
)
ORDER BY
usr.userID
, itm.itemID
Upvotes: 0
Reputation: 601
SELECT u.userId, u.firstName, i.itemId, i.itemName
FROM users u CROSS JOIN items i
LEFT OUTER JOIN useritems ui
ON u.userID = ui.userId AND i.itemId = ui.itemId
WHERE ui.itemId IS NULL
ORDER BY 1, 3;
Upvotes: 1
Reputation: 1680
This looks like a good use case for the EXCEPT operator.
SELECT U.UserID, I.itemID
FROM Users U
CROSS JOIN Items I -- Gets a set of all users and all items
EXCEPT
SELECT UI.UserID, UI.ItemID
FROM UserItems UI -- Removes the items that a user has.
Upvotes: 1
Reputation: 2328
select *
from Users as u inner join Items as i on 1=1
where not exists(select 0 from UserItems as ui where ui.userID=u.userID and i.itemID=ui.itemID)
order by userID,firstName,itemID
+--------+-----------+--------+----------+ | userID | firstName | itemID | itemName | +--------+-----------+--------+----------+ | 2 | Jill | 1 | Bucket | | 2 | Jill | 2 | Water | | 3 | John | 1 | Bucket | | 3 | John | 2 | Water | | 3 | John | 3 | Cast | | 4 | Jane | 1 | Bucket | | 4 | Jane | 2 | Water | | 4 | Jane | 3 | Cast | +--------+-----------+--------+----------+
Upvotes: 4