38

A、B、C の 3 つのテーブルがあります。ここで、A は多対 1 の B、B は多対 1 の C です。A のすべての C のリストが必要です。

私のテーブルは次のようなものです: A[id, valueA, lookupB], B[id, valueB, lookupC], C[id, valueC]. 入れ子になった 2 つの SELECT を使用してクエリを作成しましたが、DISTINCT を使用して INNER JOIN を実行できるかどうか疑問に思っています。

SELECT valueC
FROM C
INNER JOIN
(
    SELECT DISTINCT lookupC
    FROM B INNER JOIN
    (
        SELECT DISTINCT lookupB
        FROM A
    ) 
    A2 ON B.id = A2.lookupB
) 
B2 ON C.id = B2.lookupC

編集: テーブルはかなり大きく、A は 500k 行、B は 10k 行、C は 100 行であるため、基本的な内部結合を行い、最後に DISTINCT を使用すると、次のように多くの不必要な情報が得られます。

SELECT DISTINCT valueC
FROM 
C INNER JOIN B on C.id = B.lookupB
INNER JOIN A on B.id = A.lookupB

これは非常に遅いです(上記のネストされた SELECT よりも数倍遅いです。

4

4 に答える 4

15

次のテーブルを使用して MS SQL 2005 でテストを行いました: A 400K 行、B 26K 行、および C 450 行。

推定されたクエリ プランは、基本的な内部結合がネストされたサブクエリよりも 3 倍遅いことを示していましたが、実際にクエリを実行すると、基本的な内部結合はネストされたクエリの 2 倍の速さでした。最小限のサーバー ハードウェア。

どのデータベースを使用していますか? パフォーマンスが低下している場合は、おそらくインデックスの問題だと思います。

于 2008-10-02T13:38:33.113 に答える
11

あなたの1:mリレーションシップは、すでに DISTINCT JOIN を暗黙的に作成しているはずです。

ただし、目標が各 A の C だけである場合は、最も外側のクエリで DISTINCT を使用する方が簡単かもしれません。

SELECT DISTINCT a.valueA, c.valueC
FROM C
    INNER JOIN B ON B.lookupC = C.id
    INNER JOIN A ON A.lookupB = B.id
ORDER BY a.valueA, c.valueC
于 2008-10-02T08:55:44.727 に答える
3
SELECT DISTINCT C.valueC 
FROM C 
  LEFT JOIN B ON C.id = B.lookupC
  LEFT JOIN A ON B.id = A.lookupB
WHERE C.id IS NOT NULL

A と B の結果セットを制限する正当な理由がわかりません。なぜなら、A によって参照されるすべての C のリストが必要だからです。 C の一意のリストが必要でした。


編集:あなたの主張に同意します。ソリューションが少し入れ子になっているように見えても、データに関する知識を使用して結果セットを削減するための最良かつ最速の方法のようです。

使用できる明確な結合構造はありませんので、既に持っているものをそのまま使用してください:)

于 2008-10-02T08:55:56.880 に答える
1

これはあなたが意味するものですか?

SELECT DISTINCT C.valueC
FROM 
C
INNER JOIN B ON C.id = B.lookupC
INNER JOIN A ON B.id = A.lookupB
于 2008-10-02T08:54:05.560 に答える