4

この質問には答えがあると確信していますが、私はSQLが初めてで、質問の仕方がわからないので、ご容赦ください。

私はこのようなデータを持っています (これは純粋に例として省略形です)。これはpostgres dbにあります。

table1
id    value
1     111
1     112
1     113
2     111
2     112
2     116
3     111
3     122
3     123
4     126
5     123
5     125
6     111
6     112
6     116

table2
value
111
112
116

table2 のすべての値が table1 の値に存在する table1 の ID を返す必要があります。したがって、この例では、クエリは 2 と 6 を返します。

SQLでこれを行う方法はありますか? または、この結果を得ることができるデータ構造を教えていただけませんか? この結果を得るという究極のニーズに対応するために、どちらかのテーブルの構造を変更することができます

どうもありがとう。これに対する答えは命の恩人です。

4

4 に答える 4

6

次のデモを検討してください。

CREATE TEMP TABLE table1(id int, value int);
INSERT INTO table1 VALUES
 (1,111),(1,112),(1,113)
,(2,111),(2,112),(2,116)
,(3,111),(3,122),(3,123)
,(4,126)
,(5,123),(5,125)
,(6,111),(6,112),(6,116);

CREATE TEMP TABLE table2(value int);
INSERT INTO table2 VALUES
 (111)
,(112)
,(116);

SELECT t1.id
FROM   table1 t1
JOIN   table2 t2 USING (value)
GROUP  BY t1.id
HAVING count(*) = (SELECT count(*) FROM table2)
ORDER  BY t1.id;

結果:

id
-----
2
6

table1一度に提供されたすべての値で表示されるすべての ID を返しますtable2
両方のテーブルの任意の数の行で機能します。

重複行が表示される可能性がある場合は、次のtable1ようにします。

HAVING count(DISTINCT value) = (SELECT count(*) FROM table2) 
于 2011-12-08T02:14:37.757 に答える
3

正しい質問をする方法を知りたいと思うのと同じくらい私には思えます。ここでの魔法の言葉は「関係分割」です。

これはCodd関係代数の演算子の 1 つであり、それ以来、いくつかのバリエーションが提案されています。ごく最近、Chris Dateは、概念全体を画像関係に置き換えることを提案しました。

SQL には明示的な除算演算子がありません。他の演算子を使用するいくつかの回避策があり、最も適切な方法は、正確な除算または剰余のある除算、および空の除数の処理方法など、要件によって異なります。次に、通常の考慮事項があります。SQL 製品とバージョン、パフォーマンス、個人的なスタイルと好みなどです。

これらの選択に役立ついくつかの記事を次に示します。

関係分割の分かりやすさについて

分断された私たちの立場: リレーショナル分断の SQL

于 2011-12-08T14:10:57.073 に答える
1

UPDATE別の可能性:

SELECT t1.id
FROM (SELECT t1.id, t1.value
      FROM table1 t1
      JOIN  table2 t2 USING (value)
      GROUP BY t1.id, t1.value
      ORDER BY t1.id) t1
GROUP BY t1.id      
HAVING COUNT(*) = (SELECT COUNT(*) FROM table2)

EXPLAIN ANALYZEを使用する場合、行が繰り返されていても、私の答えのコストは常に 893-900 です。

于 2011-12-08T12:10:57.347 に答える
0

NOT EXISTS(... NOT EXISTS) は、リレーショナル除算の標準的なソリューションです。

SELECT DISTINCT id
FROM table1 t1
WHERE NOT EXISTS (
        SELECT * FROM table2 t2
        WHERE NOT EXISTS (
                SELECT * FROM table1 t1x
                WHERE t1x.value = t2.value
                AND t1x.id = t1.id
                )
        )
        ;

この場合、sを使用してドメインテーブルにアクセスできず、それを参照するジャンクションテーブルにしかDISTINCTアクセスできないため、 が必要です。idt1

于 2016-08-31T12:59:29.447 に答える