web-dev-qa-db-ja.com

PostgresのJOIN条件とWHERE条件

Postgres初心者はこちら。

このクエリが最適化されているかどうか疑問に思っていますか? 100%必要な値だけを結合し、すべての動的条件をWHERE句に残そうとしました。下記参照。

SELECT *
    FROM
      myapp_employees
    JOIN myapp_users ON
      myapp_users.user_id=myapp_employees.user_id
    JOIN myapp_contacts_assoc ON
      myapp_contacts_assoc.user_id=myapp_users.user_id
    JOIN myapp_contacts ON
      myapp_contacts.contact_id=myapp_contacts_assoc.contact_id
    WHERE
      myapp_contacts.value='[email protected]' AND
      myapp_contacts.type=(1)::INT2 AND
      myapp_contacts.is_primary=(1)::INT2 AND
      myapp_contacts.expired_at IS NULL AND
      myapp_employees.status=(1)::INT2 AND
      myapp_users.status=(1)::INT2
    LIMIT 1;

注:コンテキストについては、このプロシージャはユーザーが従業員でもあるかどうかを確認しています(昇格された特権/異なるユーザータイプ)。

とにかく、これは正しい方法ですか? JOIN ONには、expired_at IS NULLなどのチェックなどのステートメントがさらに含まれている必要がありますか?なぜ、またはなぜこれが意味をなさないのですか?

9
Dan

論理的にINNER JOINの結合句に条件を置いても、同じWHERESELECT句に条件を置いても、まったく違いはありません。効果は同じです。

OUTER JOINの場合は異なります!)

デフォルト設定で動作している間は、クエリプランまたはパフォーマンスにも違いはありません。 Postgresは、テーブルの数が join_collapse_limit より大きくない限り、結合とJOINWHERE条件を自由に再配置して、最適なクエリプランを探すことができます。 =(デフォルト8)。詳細:

可読性と保守性の場合、テーブルを接続する条件をそれぞれのJOIN句に配置し、一般的な条件をWHERE句に配置することは理にかなっています。

クエリは問題なく見えます。ただし、テーブルエイリアスを使用してノイズを削減します。

細部:

int2 '1'または1::int2(1)::INT2よりも賢明です。また、明確に定義された数値データ型の値と比較しながら、単純な数値定数1でも十分です。

13

いくつかのポイント.

  1. 同じ名前(_user_id_)で条件に参加する場合は、USING (user_id)ではなくON (a.user_id = b.user_id)を使用できます。これにより、冗長列が出力される可能性もなくなります(本番環境で_SELECT *_を実行している場合)。

  2. _1::int2_は問題があります。 status、および_is_primary_などはすでに_int2_です。この場合、リテラル1は自動的にint2にキャストされます。または、それらを通常のintとして格納し、計算に違いが生じたかのようにそれらをキャストダウンする場合、計算に違いはありませんが、キャストだけでは、命題が失われます。

  3. 可能であれば、:: int2はすべてbooleanとして保存する必要があります。次に、WHERE条件を簡単に書くこともできます。

  4. タイプとステータスについては、ENUMタイプが必要な場合があります。

2
Evan Carroll