Требуемый вам реляционный оператор: 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'
);