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などのチェックなどのステートメントがさらに含まれている必要がありますか?なぜ、またはなぜこれが意味をなさないのですか?
論理的に、INNER JOIN
の結合句に条件を置いても、同じWHERE
のSELECT
句に条件を置いても、まったく違いはありません。効果は同じです。
(OUTER JOIN
の場合は異なります!)
デフォルト設定で動作している間は、クエリプランまたはパフォーマンスにも違いはありません。 Postgresは、テーブルの数が join_collapse_limit
より大きくない限り、結合とJOIN
&WHERE
条件を自由に再配置して、最適なクエリプランを探すことができます。 =(デフォルト8
)。詳細:
可読性と保守性の場合、テーブルを接続する条件をそれぞれのJOIN
句に配置し、一般的な条件をWHERE
句に配置することは理にかなっています。
クエリは問題なく見えます。ただし、テーブルエイリアスを使用してノイズを削減します。
細部:
int2 '1'
または1::int2
は(1)::INT2
よりも賢明です。また、明確に定義された数値データ型の値と比較しながら、単純な数値定数1
でも十分です。
いくつかのポイント.
同じ名前(_user_id
_)で条件に参加する場合は、USING (user_id)
ではなくON (a.user_id = b.user_id)
を使用できます。これにより、冗長列が出力される可能性もなくなります(本番環境で_SELECT *
_を実行している場合)。
_1::int2
_は問題があります。 status
、および_is_primary
_などはすでに_int2
_です。この場合、リテラル1は自動的にint2にキャストされます。または、それらを通常のintとして格納し、計算に違いが生じたかのようにそれらをキャストダウンする場合、計算に違いはありませんが、キャストだけでは、命題が失われます。
可能であれば、:: int2はすべてboolean
として保存する必要があります。次に、WHERE
条件を簡単に書くこともできます。
タイプとステータスについては、ENUM
タイプが必要な場合があります。