WHERE col1, col2 IN (...) [Подзапрос SQL с использованием составного первичного ключа]
Учитывая таблицу foo
с составным первичным ключом (a,b)
, существует ли юридический синтаксис для написания запроса, например:
SELECT ... FROM foo WHERE a,b IN (SELECT ...many tuples of a/b values...);
UPDATE foo SET ... WHERE a,b IN (SELECT ...many tuples of a/b values...);
Если это невозможно, и вы не можете изменить схему, как вы могли бы выполнить эквивалент выше?
Я также собираюсь использовать термины "составной первичный ключ", "подзаголовок", "подвыбор" и "подзапрос" здесь для поиска по этим псевдонимам.
Изменить: меня интересуют ответы для стандартного SQL, а также те, которые будут работать с PostgreSQL и SQLite 3.
Ответы
Ответ 1
sqlite> create table foo (a,b,c);
sqlite> create table bar (x,y);
sqlite> select * from foo where exists (select 1 from bar where foo.a = bar.x and foo.b = bar.y);
Замените select 1 from bar
на select ... many tuples of a/b values ...
.
Или создайте временную таблицу вашего select ... many tuples of a/b values ...
и используйте ее вместо bar
..
Ответ 2
Ваш синтаксис очень близок к стандарту SQL!
Допустимо следующее: FULL SQL-92 (как подтверждено Mimer SQL-92 Validator)
SELECT *
FROM foo
WHERE (a, b) IN (
SELECT a, b
FROM bar
);
Конечно, не каждый SQL-продукт поддерживает полный SQL-92 (позор!) Если кто-то захочет увидеть этот синтаксис, поддерживаемый в Microsoft SQL Server, они могут проголосовать за него .
Еще одна конструкция SQL-92, которая более широко поддерживается (например, Microsoft SQL Server и Oracle), является INTERSECT
например.
SELECT a, b
FROM Foo
INTERSECT
SELECT a, b
FROM Bar;
Обратите внимание, что эти конструкции правильно обрабатывают значение NULL
, в отличие от некоторых других предложений здесь, например. те, которые используют EXISTS (<equality predicates>)
, конкатенированные значения и т.д.
Ответ 3
Вы совершили очень маленькую ошибку.
Вы должны положить a, b в круглые скобки.
SELECT ... FROM foo WHERE (a,b) IN (SELECT f,d FROM ...);
Это работает!
Ответ 4
Предлагаемый синтаксис IN недействителен SQL. Решение с использованием EXISTS должно работать во всех разумно совместимых SQL RDBMSes:
UPDATE foo SET x = y WHERE EXISTS
(SELECT * FROM bar WHERE bar.c1 = foo.c1 AND bar.c2 = foo.c2)
Помните, что это часто не особенно заметно.
Ответ 5
SELECT ...
FROM foo
INNER JOIN (SELECT ...many tuples of a/b values...) AS results
ON results.a = foo.a
AND results.b = foo.b
Что вы ищете?
Ответ 6
С конкатенацией это работает с PostgreSQL:
SELECT a,b FROM foo WHERE a||b IN (SELECT a||b FROM bar WHERE condition);
UPDATE foo SET x=y WHERE a||b IN (SELECT a||b FROM bar WHERE condition);
Ответ 7
JOINS
и INTERSECTS
работают в качестве замены для IN
, но они не так очевидны, как замена для NOT IN
, например: вставка строк из TableA
в TableB
, где они 't уже существует в TableB
, где PK
на обеих таблицах является составной.
В настоящее время я использую метод конкатенации выше в SQL Server, но это не очень изящное решение.
Ответ 8
Если вам нужно решение, которое не требует кортежей значений, уже существующих в таблице, вы можете объединить соответствующие значения таблиц и элементы в своем списке, а затем использовать команду "IN".
В postgres это будет выглядеть так:
SELECT * FROM foo WHERE a || '_' || b in ('Hi_there', 'Me_here', 'Test_test');
В SQL я бы предположил, что это может выглядеть примерно так:
SELECT * FROM foo WHERE CONCAT(a, "_", b) in ('Hi_there', 'Me_here', 'Test_test');
Ответ 9
Firebird использует эту формулу конкатенации:
SELECT a, b FROM foo ГДЕ a || b IN (SELECT a || b FROM bar WHERE состояние);