Подтвердить что ты не робот

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.

4b9b3361

Ответ 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 состояние);