«Где IN» с несколькими столбцами определены в стандартном SQL? - PullRequest
13 голосов
/ 09 июня 2011

Я работаю над запросом, подобным этому:

SELECT * FROM requests where (id,langid) IN (SELECT nid,langid FROM node)

Мои вопросы

это работает в mysql и postgresql? это что-то поддерживается стандартным SQL?

Я знаю, что это не лучшее решение, и JOIN будет работать, но мне это не интересно.

Ответы [ 4 ]

12 голосов
/ 09 июня 2011

Стандартным и переносимым SQL будет EXISTS .. и семантически тот же самый IN

SELECT *
FROM requests R
WHERE 
    EXISTS (SELECT *
           FROM node n
           WHERE r.id = n.nid AND r.langid = n.langid
           )

Многостолбцовый IN не переносим, ​​по крайней мере, на SQL Server или Sybase.

Другие примечания:

  • Для СОЕДИНЕНИЯ может потребоваться DISTINCT, который отличается от IN или EXISTS.
  • Последний вариант - INTERSECT, который реже поддерживается и работает как IN / EXISTS
  • IIRC некоторые доисторические версии MySQL (3.x?) Не поддерживали корреляцию для EXISTS
8 голосов
/ 09 июня 2011

Я проверил это с PostgreSQL, и он работает (он официально поддерживается ), но вы обязаны обеспечить совместимость типов столбцов id id nid и langid ↔ langid (или использовать явное приведение).

Я думаю, что это довольно стандартная конструкция.У меня есть SQL: 2003 черновик , и в предикате определено (а также упомянутый существует предикат ).

8,4

Функция

Укажите количественное сравнение.

Формат

<in predicate> ::= <row value predicand> <in predicate part 2>
<in predicate part 2> ::= [ NOT ] IN <in predicate value>
<in predicate value> ::=
<table subquery>
| ... (rest is not important here)

РЕДАКТИРОВАТЬ:

Как проверено хорошо работает и под MySQL (версия 5.0.90-log). Вот ссылка на документацию .

7 голосов
/ 09 июня 2011

Ваш запрос будет работать в Postgres. Лучше всего я знаю, не в MySQL.

Портативная версия для БД, которая его поддерживает:

SELECT * FROM requests where ROW(id,langid) IN (SELECT nid,langid FROM node)

(row является зарезервированным ключевым словом, поскольку SQL: 1999 .)

Более переносимая версия будет использовать exists(), как предлагается в другом ответе.

2 голосов
/ 13 июня 2011

Ваш код SQL действителен в отношении стандарта SQL-92. Вы можете подтвердить это самостоятельно, используя онлайн-валидатор Mimer SQL-92 (доступны также версии SQL-99 и SQL: 2003 ). Однако, поскольку это особенность Full SQL-92, он не так широко реализован, как, возможно, и должно быть.

С относительной точки зрения рассматриваемый оператор - это semi-join , для которого ни один из стандартов SQL (и ни одно из расширений вендоров?) Не имеет явного синтаксиса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...