What kind of join do I need?

Solution 1:

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'

Solution 2:

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

Solution 3:

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'
              );