7

4 つのテーブルを持つ PostgreSQL データベースを取得しました。

表 A

---------------------------
| ID | B_ID | C_ID | D_ID |
---------------------------
| 1  |  1   | NULL | NULL |
---------------------------
| 2  | NULL |   1  | NULL |
---------------------------
| 3  |  2   |   2  |   1  |
---------------------------
| 4  | NULL | NULL |   2  |
---------------------------

表 B

-------------
| ID | DATA |
-------------
| 1  | 123  |
-------------
| 2  | 456  |
-------------

表 C

-------------
| ID | DATA |
-------------
| 1  | 789  |
-------------
| 2  | 102  |
-------------

表 D

-------------
| ID | DATA |
-------------
| 1  | 654  |
-------------
| 2  | 321  |
-------------

ブース ID の 1 つが null でない場合にのみ、テーブル B のデータとテーブル C のデータを結合した結果セットを取得しようとしています。

SELECT "Table_A"."ID", "Table_A"."ID_B", "Table_A"."ID_C", "Table_A"."ID_D", "Table_B"."DATA", "Table_C"."DATA"
    FROM "Table_A"
        LEFT JOIN "Table_B" on "Table_A"."ID_B" = "Table_B"."ID"
        LEFT JOIN "Table_C" on "Table_A"."ID_C" = "Table_C"."ID"
    WHERE "Table_A"."ID_B" IS NOT NULL OR "Table_A"."ID_C" IS NOT NULL;

これは推奨されますか、それとも複数のクエリに分割する必要がありますか?

これらのテーブル間で内部結合を行う方法はありますか?

私が期待する結果は次のとおりです。

-------------------------------------------------
| ID | ID_B | ID_C | ID_D | DATA (B) | DATA (C) |
-------------------------------------------------
| 1  |   1  | NULL | NULL |   123    |   NULL   |
-------------------------------------------------
| 2  | NULL |  1   | NULL |   NULL   |   789    |
-------------------------------------------------
| 3  |   2  |  2   | NULL |   456    |   102    |
-------------------------------------------------

編集: ID_B , ID_C,ID_Dはテーブルへの外部キーですtable_b, table_c,table_d

4

4 に答える 4

5

WHERE "Table_A"."ID_B" IS NOT NULL OR "Table_A"."ID_C" IS NOT NULL;、B テーブルと C テーブルの対応する句に置き換えることができますWHERE "Table_B"."ID" IS NOT NULL OR "Table_C"."ID" IS NOT NULL;。これは、table_a.id_b と table_a.id_c が B テーブルと C テーブルの外部キーでない場合にも機能します。それ以外の場合、{ 5, 5,5,5} を含む table_a 行は、B テーブルと C テーブルから 2 つの NULL 行を取得します。

SELECT ta."ID" AS a_id
        , ta."ID_B" AS b_id
        , ta."ID_C" AS c_id
        , ta."ID_D" AS d_id
        , tb."DATA" AS bdata
        , tc."DATA" AS cdata
FROM "Table_a" ta
LEFT JOIN "Table_B" tb on ta."ID_B" = tb."ID"
LEFT JOIN "Table_C" tc on ta."ID_C" = tc."ID"
WHERE tb."ID" IS NOT NULL OR tc."ID" IS NOT NULL
        ;
于 2013-05-25T11:01:30.007 に答える
2

あなたの要件を考えると、あなたのクエリは私には良いようです。

別の方法は、プロジェクションでネストされた選択を使用することですが、ネストされた選択は通常ネストされたループになるため、データ、インデックス、および制約によっては遅くなる可能性がありますが、結合はマージ結合またはネストされたループとして実行できます。

SELECT 
    "Table_A"."ID", 
    "Table_A"."ID_B", 
    "Table_A"."ID_C", 
    "Table_A"."ID_D", 
    (SELECT "DATA" FROM "Table_B" WHERE "Table_A"."ID_B" = "Table_B"."ID"),
    (SELECT "DATA" FROM "Table_C" WHERE "Table_A"."ID_C" = "Table_C"."ID")
FROM "Table_A"
WHERE "Table_A"."ID_B" IS NOT NULL OR "Table_A"."ID_C" IS NOT NULL;

Postgres が(Oracle のように)スカラー サブクエリ キャッシングを行う場合、ネストされた select は、データの繰り返しが多い場合に役立つ可能性があります。Table_A

于 2013-05-25T09:32:30.947 に答える
0

一般的に推奨される方法は、1 つのクエリのみで実行し、特に並べ替え (並べ替え) やページネーション (制限 ... オフセット ...) などの他の操作を後で追加する場合は、データベースにできるだけ多くの作業をさせることです。後で。いくつかの測定を行いましたが、リストなどのより高いレベルのコレクションを使用する場合、Java/Scala でより高速に並べ替え/ページ付けする方法はありません。

RDBMS は単一の複雑なステートメントを非常にうまく処理しますが、多くの小さなクエリを処理するのは困難です。たとえば、1 つのクエリで「1 つ」と「複数のリレーション」をクエリすると、1 + n の select ステートメントでこれを行うよりも高速になります。

外部結合に関しては、測定を行っており、内部結合と比較して実際のパフォーマンスの低下はありません。したがって、データ モデルやクエリで外部結合が必要な場合は、そのまま実行してください。パフォーマンスの問題であった場合は、後で調整できます。

null 比較に関しては、データ モデルを最適化できることを示している可能性がありますが、それは単なる推測です。これらの列で null が許可されないように設計を改善できる可能性があります。

于 2013-05-25T11:16:00.493 に答える