2012-07-02 18 views
16

同じテーブルにある複数の列から一意のNULL以外の値を返す単一のSQL文を作成しようとしています。例えば同じテーブル内の複数の列から異なる値を選択

SELECT distinct tbl_data.code_1 FROM tbl_data 
     WHERE tbl_data.code_1 is not null 
UNION 
SELECT tbl_data.code_2 FROM tbl_data 
     WHERE tbl_data.code_2 is not null; 

、tbl_dataは以下の通りである:AB、BC、DE:

id code_1 code_2 
--- -------- ---------- 
1 AB  BC 
2 BC   
3 DE  EF 
4    BC 

を上記の表は、SQLクエリは、2つの列、すなわち、からすべての一意の非NULL値を返すべき、EF。

私はかなり新しいSQLです。上記の私のステートメントは動作しますが、カラムが同じテーブルから来ているので、このSQL文を書くためのよりきれいな方法がありますか?

SELECT derivedtable.NewColumn 
FROM 
(
    SELECT code_1 as NewColumn FROM tbl_data 
    UNION 
    SELECT code_2 as NewColumn FROM tbl_data 
) derivedtable 
WHERE derivedtable.NewColumn IS NOT NULL 

UNIONはすでに複合クエリーからDISTINCTの値を返します。

+0

そのテーブル構造はあなたのDBが正規化されていないと感じています... – gdoron

+4

最初のクエリで 'distinct'は必要ありません - ' union'がそれを行います。 – Blorgbeard

+0

@ gdoron:コードは、実際に繰り返すことができる様々な指定に対応しており、すなわち特定のレコードはコード1および2に対してBCおよびBCを有することができる。コード1対2の指定もまた重要である。様々なコードの第3のテーブルルックアップテーブルがある。最高ではありませんが、それが私が扱っているものです。 – regulus

答えて

18

あいまいなテキストデータではなく、問題のコードを含めると、同じデータを扱うことができます。 UNIONオペレータが重複する行がなくなるため、コメント

CREATE TABLE tbl_data (
    id INT NOT NULL, 
    code_1 CHAR(2), 
    code_2 CHAR(2) 
); 

INSERT INTO tbl_data (
    id, 
    code_1, 
    code_2 
) 
VALUES 
    (1, 'AB', 'BC'), 
    (2, 'BC', NULL), 
    (3, 'DE', 'EF'), 
    (4, NULL, 'BC'); 

Blorgbeardとして、あなたの溶液中のDISTINCT句は不要である:ここで私が想定しているサンプル・スキーマとデータがあります。重複を排除しないUNION ALL演算子がありますが、ここでは適切ではありません。

SELECT code_1 
FROM tbl_data 
WHERE code_1 IS NOT NULL 
UNION 
SELECT code_2 
FROM tbl_data 
WHERE code_2 IS NOT NULL; 

二つの列が同じテーブルにあることは問題ではありません。

DISTINCT句を使用せずにクエリを書き換えることで、この問題への罰金のソリューションです。列が異なる表にあってもソリューションは同じになります。あなたが二回同じフィルタ句を指定の冗長性を気に入らない場合

、あなたはそれをフィルタリングする前に、仮想テーブルでユニオンクエリをカプセル化することができます

SELECT code 
FROM (
    SELECT code_1 
    FROM tbl_data 
    UNION 
    SELECT code_2 
    FROM tbl_data 
) AS DistinctCodes (code) 
WHERE code IS NOT NULL; 

私はもっと醜い秒の構文を見つけますしかし、論理的にはそれほどうまくありません。しかし、どちらの方がうまくいくのですか? 、

The query optimizer produces this execution plan for both queries: two table scans, a concatenation, a distinct sort, and a select.

SQL Serverは、2つのクエリに対して同じ実行計画を生成した場合:

は、私は、SQL Server 2005のクエリオプティマイザは、2つの異なるクエリで同じ実行計画を生成することを実証するsqlfiddleを作成しましたそれらは事実上同様に論理的に同等である。

は、あなたの質問では、クエリの実行プランに上記の比較:

The DISTINCT clause makes SQL Server 2005 perform a redundant sort operation.

クエリオプティマイザは、その任意の重複を知らないので、DISTINCT句は、SQL Server 2005は冗長な並べ替え操作を実行します最初のクエリでDISTINCTによって除外されたものは、とにかくUNIONによって除外されます。

このクエリは他の2つのクエリと論理的には同じですが、冗長な操作では効率が低下します。大規模なデータセットでは、ここで2つ以上の結果セットを返すためにクエリが長くかかると思います。私の言葉をそれに服用しないでください。自分の環境で実験して確かめてください!

+0

この説明をありがとう! – regulus

+0

ベストアンサーの1つ私は今まで読んだことがあると思います。優れた詳細と例、テスト結果 – htm11h

4

SubQueryのようなものを試してみてください。

+0

この例をありがとう! – regulus

+0

ありがとう!私が探している完璧な答えに見えます! – NidhinSPradeep