我需要什么样的联接?

时间:2011-08-11 22:34:18

标签: sql semi-join

我有一张投票表:

 votes
-----------------
 userid   gameid
-------  --------
   a        1
   a        2
   a        3
   b        1
   b        2

和一个游戏桌:

 games
----------------
 gameid   title
 ------   ------
    1       foo
    2       bar
    3       fizz
    4       buzz

我将使用什么样的联接来执行查询“从游戏中选择* [用户A在游戏中投票]”?

我已尝试关注Jeff's guide,但我没有得到预期的结果。

4 个答案:

答案 0 :(得分:6)

您可以使用INNER联接来建立公共gameid字段之间的关系;

select
  votes.userid,
  games.title
from games
  inner join votes on (votes.gameid = game.gameid)
where
  votes.userid = 'a'

答案 1 :(得分:1)

这可以通过投票获得游戏:

SELECT
   g.title
   v.userid
FROM
   games g

   INNER JOIN votes v
   ON g.gameid = v.gameid

这可以让你获得所有游戏,即使没有投票:

SELECT
   g.title
   v.userid
FROM
   games g

   LEFT JOIN votes v
   ON g.gameid = v.gameid

答案 2 :(得分:1)

您需要的关系运算符是semijoin

大多数SQL产品缺少明确的半连接运算符或关键字。标准SQL-92具有MATCH (subquery)谓词但未广泛实现(真正的关系语言Tutorial D使用关键字MATCHING作为其半连接运算符。)

半连接当然可以使用其他SQL谓词编写。最常见的使用EXISTSIN (subquery)

根据数据,可以使用SELECT DISTINCT..INNER JOIN。但是,在您的情况下,您使用的是SELECT * FROM ...,而INNER JOIN将投票在投票表上,导致userid附加到列列表以及gameid的重复列(如果您选择的SQL产品支持它,使用NATURAL JOIN将解决重复列问题并且意味着您也将省略ON子句。

使用INTERSECT是另一种可行的方法,如果您的SQL产品支持它,并且再次取决于数据(特别是,当两个表的标题相同时)>

就个人而言,我更喜欢在SQL中使用EXISTS来表示半连接,因为连接子句在编写的代码中更接近,并且不会导致在连接表上进行投影,例如

SELECT *
  FROM games
 WHERE EXISTS (
               SELECT * 
                 FROM votes AS v
                WHERE v.gameid = games.gameid
                      AND v.userid = 'a'
              );

答案 3 :(得分:0)

似乎,鉴于您的有限描述,以下内容将为您提供用户A在游戏中投票的游戏列表:

select g.gameid, g.title
from games g
inner join votes v
on v.gameid = g.gameid
where v.userid = 'a'