web-dev-qa-db-ja.com

SQLでDISTINCT内部結合を使用する

A、B、Cの3つのテーブルがあり、Aは多対1、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は50万行、Bは1万行、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よりも大きさが倍遅い)。

34

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

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

使用しているデータベースは何ですか?パフォーマンスの低下が見られる場合、それはおそらくインデックスの問題であると考えています。

15
Darrel Miller

あなたの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
9
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の一意のリストが必要でした。


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

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

3
VVS

これはどういう意味ですか?

SELECT DISTINCT C.valueC
FROM 
C
INNER JOIN B ON C.id = B.lookupC
INNER JOIN A ON B.id = A.lookupB
0
kristian