查询三个表之间不存在关系的位置

时间:2017-08-03 17:26:52

标签: sql sql-server relational-database

我有三个表(Users,Items,UserItems),其中UserItems是Users和Items之间的多对多关系。我需要的是一个获取用户没有的所有项目的查询。

我在这里创建了一个带有一些假数据的SQL Fiddle示例: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 );

期望的结果用户和他们没有的物品:

---------------------------------
| 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     |
---------------------------------

注意:Jack不需要在结果中,因为他有三个项目。

4 个答案:

答案 0 :(得分:4)

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     |
+--------+-----------+--------+----------+

答案 1 :(得分:1)

这看起来像是EXCEPT运算符的一个很好的用例。

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.

答案 2 :(得分:1)

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;

答案 3 :(得分:0)

NOT EXISTS似乎非常适合

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