What kind of join do I need?

后端 未结 4 980
走了就别回头了
走了就别回头了 2020-11-27 23:01

I have a votes table:

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


        
相关标签:
4条回答
  • 2020-11-27 23:41

    This gets you the games with a vote:

    SELECT
       g.title
       v.userid
    FROM
       games g
    
       INNER JOIN votes v
       ON g.gameid = v.gameid
    

    This gets you all of the games, even if not voted on:

    SELECT
       g.title
       v.userid
    FROM
       games g
    
       LEFT JOIN votes v
       ON g.gameid = v.gameid
    
    0 讨论(0)
  • 2020-11-27 23:43

    Seems like, given your limited description, the following would get you a list of games where user A voted on the game:

    select g.gameid, g.title
    from games g
    inner join votes v
    on v.gameid = g.gameid
    where v.userid = 'a'
    
    0 讨论(0)
  • 2020-11-27 23:54

    The relational operator you require is semijoin.

    Most SQL products lacks an explicit semijoin operator or keyword. Standard SQL-92 has a MATCH (subquery) predicate but is not widely implemented (the truly relational language Tutorial D uses the keyword the MATCHING for its semijoin operator).

    A semijoin can of course be written using other SQL predicates. The most commonly seen use EXISTS or IN (subquery).

    Depending on the data it may be possible to use SELECT DISTINCT..INNER JOIN. However, in your case you are using SELECT * FROM ... and an INNER JOIN will project over the votes table resulting in userid being appended to the column list along with a duplicate column for gameid (if your SQL product of choice supports it, using NATURAL JOIN would solve the duplicate column problem and mean you would omit the ON clause too).

    Using INTERSECT is another possible approach if your SQL product supports it and again depending on the data (specifically, when the headings of the two tables are the same)>

    Personally, I prefer to use EXISTS in SQL for semijoin because the join clauses are closer together in the written code and doesn't result in projection over the joined table e.g.

    SELECT *
      FROM games
     WHERE EXISTS (
                   SELECT * 
                     FROM votes AS v
                    WHERE v.gameid = games.gameid
                          AND v.userid = 'a'
                  );
    
    0 讨论(0)
  • 2020-11-27 23:58

    You would use an INNER join to establish the relationship between the common gameid field;

    select
      votes.userid,
      games.title
    from games
      inner join votes on (votes.gameid = game.gameid)
    where
      votes.userid = 'a'
    
    0 讨论(0)
提交回复
热议问题