2011-08-11 82 views
2

我有一个投票表:我需要什么样的连接?

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

和游戏桌:

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

我会用什么样的联接执行查询“SELECT * FROM游戏中[用户A投票游戏]”?我试过Jeff's guide,但我没有得到预期的结果。

回答

6

您将使用INNER连接建立常见的gameid字段之间的关系;

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

完美!谢谢。我确实在做错我的“上”条款,我认为这是我的第一个问题。 Inner Join是有意义的,因为我不希望任何两个记录都不匹配。 – xdumaine

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

好的答案,给出了一个模棱两可的问题。 – Karl

0

好像,给你限制说明,以下内容会为您提供用户A在游戏中投票的游戏列表:

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

您需要的关系运算符是semijoin

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

当然可以使用其他SQL谓词编写一个semijoin。最常见的用途是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' 
      ); 
+0

这很有趣。它实现与Inner Join相同的功能,但不返回票表中的值。是否有任何显着的性能差异? – xdumaine