Какой тип объединения мне нужен? - PullRequest
2 голосов
/ 12 августа 2011

У меня есть таблица голосов:

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

и игровой стол:

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

Какой тип объединения я бы использовал для выполнения запроса «Выбрать * из игр, в которых [пользователь А проголосовал за игру]»?

Я пытался следовать Руководству Джеффа , но я не получаю ожидаемых результатов.

Ответы [ 4 ]

6 голосов
/ 12 августа 2011

Вы бы использовали INNER объединение для установления связи между общим полем gameid;

select
  votes.userid,
  games.title
from games
  inner join votes on (votes.gameid = game.gameid)
where
  votes.userid = 'a'
1 голос
/ 12 августа 2011

Требуемый вам реляционный оператор: semi-join .

В большинстве продуктов SQL отсутствует явный оператор или ключевое слово semi-join. Стандартный SQL-92 имеет предикат MATCH (subquery), но широко не применяется (действительно реляционный язык Учебное пособие D использует ключевое слово MATCHING для своего оператора semi-join).

Полусоединение, конечно, может быть написано с использованием других предикатов SQL. Наиболее часто встречающееся использование EXISTS или IN (subquery).

В зависимости от данных может быть возможно использовать SELECT DISTINCT..INNER JOIN. Однако в вашем случае вы используете SELECT * FROM ..., а INNER JOIN будет проецироваться поверх таблицы голосов, в результате чего userid будет добавлен в список столбцов вместе с дублирующимся столбцом для gameid (если ваш продукт SQL поддерживает выбор это, использование NATURAL JOIN решит проблему с дублирующимся столбцом и означает, что вы опустите также предложение ON).

Использование INTERSECT - это еще один возможный подход, если ваш продукт SQL поддерживает его, и опять же, в зависимости от данных (в частности, когда заголовки двух таблиц совпадают)>

Лично я предпочитаю использовать EXISTS в SQL для полусоединения, потому что в соединяемом коде предложения соединения находятся ближе друг к другу и не приводят к проекции на объединенную таблицу, например.

SELECT *
  FROM games
 WHERE EXISTS (
               SELECT * 
                 FROM votes AS v
                WHERE v.gameid = games.gameid
                      AND v.userid = 'a'
              );
1 голос
/ 12 августа 2011

Это дает вам игры с голосованием:

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 голосов
/ 12 августа 2011

Похоже, учитывая ваше ограниченное описание, следующее даст вам список игр, в которых за игру проголосовал пользователь A:

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