複合主キー(a,b)
を持つテーブルfoo
が与えられた場合、次のようなクエリを記述するための正当な構文があります。
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で動作する回答にも興味があります。
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
の代わりに使用します。
構文は標準SQLに非常に近いです!
以下は有効なFULL SQL-92です( Mimer SQL-92 Validator で確認済み)
_SELECT *
FROM foo
WHERE (a, b) IN (
SELECT a, b
FROM bar
);
_
もちろん、すべてのSQL製品が完全なSQL-92(恥ずかしい!)をサポートしているわけではありません。MicrosoftSQL Serverでサポートされているこの構文を見たい人は、投票できます here 。
(たとえば、Microsoft SQL ServerとOracleによって)より広くサポートされているSQL-92コンストラクトは、INTERSECT
です。
_SELECT a, b
FROM Foo
INTERSECT
SELECT a, b
FROM Bar;
_
これらの他の提案のいくつかとは異なり、これらのコンストラクトはNULL
値を適切に処理することに注意してください。 EXISTS (<equality predicates>)
、連結値などを使用するもの.
あなたは1つの非常に小さな間違いをしました。 a、bを括弧で囲む必要があります。
SELECT ... FROM foo WHERE (a,b) IN (SELECT f,d FROM ...);
動作します!
提案されたIN構文は有効なSQLではありません。 EXISTSを使用したソリューションは、合理的に準拠したすべてのSQL RDBMSで機能するはずです。
UPDATE foo SET x = y WHERE EXISTS
(SELECT * FROM bar WHERE bar.c1 = foo.c1 AND bar.c2 = foo.c2)
多くの場合、これは特にパフォーマンスが高いわけではないことに注意してください。
SELECT ...
FROM foo
INNER JOIN (SELECT ...many tuples of a/b values...) AS results
ON results.a = foo.a
AND results.b = foo.b
あなたが探しているものは?
連結を使用すると、これは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);
テーブルに既に存在する値のタプルを必要としないソリューションが必要な場合は、リスト内の関連するテーブルの値とアイテムを連結し、「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');
Firebirdは次の連結式を使用します。
SELECT a、b FROM foo WHERE a || b IN(SELECT a || b FROM bar WHERE条件);
JOINS
およびINTERSECTS
はIN
の代替としては正常に機能しますが、NOT IN
の代替としてそれほど明確ではありません。たとえば、TableA
から行を挿入します。 TableB
がTableB
にまだ存在しない場合、両方のテーブルのPK
が複合である場合。
現在、SQL Serverで上記の連結方法を使用していますが、あまりエレガントなソリューションではありません。