2012-02-02 5 views
4

はの私は、次の表があるとしましょう:Postgresの左テーブルの行のサブセットを効率的にLEFT OUTER JOINできますか?

SELECT * 
FROM table_1 
LEFT OUTER JOIN table_2 USING (id_a) 

id_a name id_b 
1  c  1 
1  c  2 
2  a  1 
2  a  2 
3  b 

を今すぐ「のtable_1から」実際のような複雑なサブクエリであることを想像:

table_1     table_2 
id_a name    id_a id_b 
1  c    1  1 
2  a    1  2 
3  b    2  1 
         2  2 

今すぐ登録しよう、次のLEFT OUTERを考えます

SELECT * FROM huge_table WHERE expensive_conditions_producing_three_rows 

サブクエリを完全に再実行せずに、最小の名前で左側の行にのみ結合するクエリを記述できますか?サブクエリを自由にコントロールできると仮定できます。つまり、必要に応じてORDER BYを追加できます。言い換えれば

、最終的な結果は次のようになります。

id_a name id_b 
1  c 
2  a  1 
2  a  2 
3  b 

私は一時テーブルにサブクエリ結果を配置するSELECT INTOを使用して検討しました。次に、JOIN ON条件で使用する最小値を計算することは問題にはなりません。しかし、それが唯一の解決策でない限り、私はこれを避けることを好むでしょう。

編集:PGのバージョンに関係なく、数日待ってから、最高のソリューションを受け入れるようにします。しかし、PG 8.3以前で動作するものは大いに評価されるでしょう。

+0

は、これらのHTTPを使用してみました。 postgresql.org/docs/8.4/static/queries-with.html? –

+0

どのPostgresのバージョンですか? –

+0

似たようなことをしている他の人に質問を有効にしたかったので、私はバージョンを指定しませんでした。しかし、私は個人的にはPG 8.3で動作するものを見ることが大好きです。 – DNS

答えて

3

はそのためCTE (common table expression)(PostgreSQLの8.4以降で利用可能な)を使用してください:

WITH cte AS (
    SELECT id_a, name 
    FROM table_1 
    WHERE expensive_conditions_producing_three_rows 
    ) 
SELECT c.id_a, c.name, t2.id_b 
FROM cte c 
LEFT JOIN table2 t2 ON t2.id_a = c.id_a 
        AND t2.name = (SELECT min(name) FROM cte) 
+0

PostgreSQLについてはわかりませんが、SQL Serverでは、 'cte'が2回評価されるため、これはおそらくサブクエリ全体を再実行せずに*失敗するでしょう。 –

+0

@AndriyM:PostgreSQLでは確かにそうではありません。 (確かに検証するためにテストされましたが、それは私の時間の無駄でした)。CTEの**全体のポイント**は、クエリを再実行せずに結果の値を使用することです。さて、私はSQLサーバについて知らないが、私はそれが逆のことを行うには十分に愚かであると強く疑う。 –

+2

SQL Serverでは、CTEは一時テーブルよりもビューに似ています。同じクエリでビューを複数回参照した場合、ビューが複数回評価される可能性があるという事実に備えて準備されていると思います。 CTE(SQL Serverの場合)と同じです。オプティマイザはいくつかの再評価を排除するかもしれないが、それは保証されるものではない。 –

5

(PostgreSQLの8.4から入手可能)Window functionsを使用して:// WWW:

SELECT * 
FROM 
     (SELECT * 
      , ROW_NUMBER() OVER (ORDER BY SomeColumn) AS RowNum 
     FROM table_1 
    ) AS a 
    LEFT JOIN 
     table_2 AS b 
    ON 
     (join condition) 
    AND 
     a.RowNum = 1 
関連する問題