SQL Server - 在关联表中选择具有特定多个条目的记录

时间:2009-11-18 01:08:08

标签: join subquery associative

我在SQL Server中工作时出现以下示例问题。 Brandon更喜欢PC和Mac,Sue更喜欢PC,而Alan更喜欢Mac。数据将表示如下。我不得不在这里做出一些妥协,但希望你能得到这样的结果:

表1:用户

uID (INT PK), uName (VARCHAR)
1        'Brandon'
2        'Sue'
3        'Alan'

表2:计算机

cID (INT PK), cName (VARCHAR)
1        'Mac'
2        'PC'

表3:UCPref - 存储每个用户的计算机首选项

uID (INT FK), cID (INT FK)
1        1
1        2
2        1
3        2

现在,如果我想选择喜欢PC的OR Mac的每个人都很容易。有十几种方法可以做到这一点,但是如果我有一个输入的项目列表,那么IN子句非常简单:

SELECT u.uName
FROM User u
INNER JOIN UCPref p ON u.uID = p.uID
WHERE cID IN (1,2)

我遇到的问题是,当我只想选择喜欢BOTH PC和Android的人时会发生什么?我可以在多个子查询中执行此操作,但这不是很可扩展。

SELECT u.uName
FROM User u
INNER JOIN UCPref p ON u.uID = p.uID
WHERE u.uID IN (SELECT uID FROM UCPref WHERE cID = 1)
AND u.uID IN (SELECT uID FROM UCPref WHERE cID = 2)

如何编写此查询,以便您可以返回喜欢多台计算机的用户,同时考虑到可能有数百甚至数千种不同类型的计算机(意味着没有子查询)?如果只有你可以修改IN子句以获得像'ALL'这样的关键词来表示你只想匹配括号中包含所有项目的那些记录?

SELECT u.uName
FROM User u
INNER JOIN UCPref p ON u.uID = p.uID
WHERE cID IN *ALL* (1,2)

1 个答案:

答案 0 :(得分:0)

使用JOIN:

SELECT u.uname
  FROM USERS u
  JOIN UCPREF ucp ON ucp.uid = u.uid
  JOIN COMPUTER mac ON mac.cid = ucp.cid
                   AND mac.cname = 'Mac'
  JOIN COMPUTER pc ON pc.cid = ucp.cid
                  AND pc.cname = 'PC'

我正在使用表别名,因为我正在两次加入同一个表。

使用EXISTS:

SELECT u.uname
  FROM USERS u
  JOIN UCPREF ucp ON ucp.uid = u.uid
 WHERE EXISTS (SELECT NULL
                 FROM COMPUTER c
                WHERE c.cid = ucp.cid
                  AND c.cid IN (1, 2)
             GROUP BY c.cid 
               HAVING COUNT(*) = 2)

如果您要使用IN子句,则必须使用GROUP BY/HAVING,但COUNT()存在风险。有些db不允许超过*,而MySQL允许DISTINCT ...。问题是,如果你不能在计数中使用DISTINCT,你可以获得值2的两个实例,它对SQL有效 - 给你一个误报。