web-dev-qa-db-ja.com

それぞれの個別のAのクエリのWhere Table 1(A、B、C)には、Table 2(B、C)のすべての行と一致する行があります

ここでクエリを最適化しようとしています:

表1(A、B、C)および表2(B、C)

与えられた表1には、Aごとに多くの固有のタプル(B、C)が含まれています


(1.A、1.B、1.C)を選択します

1.Aが異なる特定の行のセットの場合、行のセットは、1.B = 2.Bおよび1.C = 2.Cである2のすべての行を集合的に満たす必要があります。


表1

| A | B  | C  |
|---|----|----|
| 1 | B1 | C1 |
| 1 | B2 | C2 |
| 2 | B1 | C1 |
| 2 | B2 | C2 |
| 2 | B3 | C3 |
| 3 | B1 | C1 |

表2

| B  | C  |
|----|----|
| B1 | C1 |
| B2 | C2 |

結果

| A | B  | C  |
|---|----|----|
| 1 | B1 | C1 |
| 1 | B2 | C2 |
| 2 | B1 | C1 |
| 2 | B2 | C2 |
| 2 | B3 | C3 |

(テーブル2の両方の行に一致しなかったため、3つだけが除外されました)

現在の実装は動的SQLです

select Result.A
from
(
SELECT vtab1.A
FROM table1 vtab1
where vtab1.[B]= 'B1' and vtab1.[C] = 'C1'
union all
SELECT b.VaultObjectId 
FROM table1 vtab2
where vtab2.[B]= 'B2' and vtab2.[C] = 'C2'
) AS Result
Group By A
HAVING 
COUNT(A) = 2

ただし、これはすべて動的に生成され、Aを対応するBに再マージしません(これは十分簡単だと思います)。

関連:後で使用するクエリに「名前を付ける」方法はありますか(計算されませんが、延期されますか?)

2
Daniel Green
select * 
from t1 
where t1.a in ( select t1.a    
                  from t1   
                  join t2 
                    on t2.b = t1.b 
                   and t2.c = t2.c
                 group by t1.a 
                having count(*) = (select count(*) from t2)
              )
1
paparazzo

関係分割の課題に対処する最も簡単な方法は、質問を否定的な形式で表現することです。同じA値を持ち、BおよびC値が一致するT1の行。最初は奇妙に思われますが、慣れればSQLへの変換は即時かつエレガントで、通常は最も効率的です。

SELECT  * 
FROM    T1
WHERE   NOT EXISTS  (
                    SELECT  NULL
                    FROM    T2
                    WHERE   NOT EXISTS  (
                                        SELECT  NULL 
                                        FROM    T1 AS T1A
                                        WHERE   T1A.B = T2.B
                                                AND
                                                T1A.C = T2.C
                                                AND
                                                T1A.A = T1.A
                                        )
                    );
1
SQLRaptor