2012-01-05 1 views
6

colAからcolBにない値をすべてmytableから戻す必要があります。私が使用しています:それはしかし、働いている他の列にない1つの列のすべての値を効率的に選択する

SELECT DISTINCT(colA) FROM mytable WHERE colA NOT IN (SELECT colB FROM mytable) 

クエリが完了するまでに過度に長い時間がかかっています。

これを行うには、より効率的な方法はありますか?

+0

'NOT IN'はセットサイズが大きくなるにつれて減速し、' NOT IN'節に含まれる行の数には限界があります。小さな結果セット以外では、2つの結果セットの違いを得るために他の手段を使用する方が良いことがわかりました。 – Paul

+0

パフォーマンスについて言及するときは、RDBMSに名前を付けるか、次善の回答を得る必要があります。 –

答えて

10

DISTINCT colAに括弧がありません。 DISTINCTは機能ではありません。

SELECT DISTINCT colA 
FROM mytable 
WHERE colA NOT IN (SELECT DISTINCT colB FROM mytable); 

サブセレクトにもDISTINCTが追加されました。重複が多い場合は、クエリを高速化できます。

DBMSに応じて、CTEがより高速になる場合があります。私は、さらにvalBに値を除外するために、代替としてLEFT JOINを発揮し、GROUP BYと異なる値を取得する別の方法:

WITH x AS (SELECT colB FROM mytable GROUP BY colB) 
SELECT m.colA 
FROM mytable m 
LEFT JOIN x ON x.colB = m.colA 
WHERE x.colB IS NULL 
GROUP BY m.colA; 

あるいは、さらに簡略化され、そして平野サブクエリ(おそらく最速)と:

SELECT DISTINCT m.colA 
FROM mytable m 
LEFT JOIN mytable x ON x.colB = m.colA 
WHERE x.colB IS NULL; 

スピードのための決定的な要因は、インデックスになります。このクエリを高速にするには、インデックスをcolAcolBにする必要があります。

+0

ありがとう、私はしようとしました: 'SELECT DISTINCT m1.colA from mytable m1 LEFT JOIN mytable m2 ON(m1.colA = m2.colB)m2.colAはNULL ORDER BY m1です。colA ASC'となり、数桁速く動作しているようです。これは質問に投稿したコードと同じですか?私が何かを逃してしまったかもしれないという疑いがあるのはずっと速いです。 – Flash

+0

@Andrew:申し訳ありませんが、あなたの質問には誤字があります。 'WHERE m2.colB IS NULL'でなければなりません。 'colB'の値が重複している場合は、** LE ** JOIN(SELECT DISTINCT colB FROM mytable)m2 m2.colB = m1.colA' **の方が速いかもしれません。 –

+0

@Andrew: 'm2.colA'はここで' m2.colB'がNULLの場合は常に 'NULL'ですが、' m2.colB'がNULLでなくてもNULLにすることができます。だから正しい(そして速い!)形式は、 'WHERE m2.colB IS NULL'です。 ** ** 'colA'がNOT NULLに定義されている場合、上記のクエリは正しいです。 –

6

あなたはexistsを使用することができます。

select distinct 
    colA 
from 
    mytable m1 
where 
    not exists (select 1 from mytable m2 where m2.colB = m1.colA) 

existsはすぐに値を一致させるためにセミが-参加しません。 not inは結果セット全体を完了してからorを実行します。 existsは通常、テーブルの値が高速です。

+0

このクエリの仕組みを説明できますか? – Flash

+0

@Andrew - はい!それは、 'colB'が' colA'と同じである 'mytable'からの行がないところに別個の' colA'をつかんでいます。 – Eric

0

2つのSELECTクエリを効果的に比較するEXCEPT演算子を使用できます。 EXCEPT DISTINCTは一意の値のみを返します。 OracleのMINUS演算子はEXCEPT DISTINCTと等価です。