Postgresql
JOIN 或 WHERE 子句中的平等?效率和風格
在下面的兩個查詢中,哪個對 postgresql 最有效?並且在可讀性等方面具有更好的風格。
不同之處在於語句的位置
doctor.type != 'surgeon'
在 WHERE 子句中:
SELECT practice.name, doctor.name FROM doctor JOIN practice ON (doctor_code = code) WHERE doctor.name LIKE '%son' AND (doctor.type != 'surgeon');
或在 JOIN 子句中:
SELECT practice.name, doctor.name FROM doctor JOIN practice ON (doctor_code = code AND doctor.type != 'surgeon') WHERE doctor.name LIKE '%son';
說到風格,你可以在幾個地方改進:
除了克雷格已經寫過的內容。
- 有一個條件只涉及子句中的
doctor
表JOIN
,而另一個條件在子句中是不一致的WHERE
。保持一致,兩者都或沒有。最好將它們放在WHERE
子句中,而連結兩個表的條件進入JOIN
子句 - 可能使用USING
. 見下文。- 對某些列 (
doctor.name
,doctor.type
) 進行表限定也是不一致的,但對其他列 ( ) 則不是code
。在較大的查詢中,最好始終對所有列進行表限定以避免命名衝突。- “名字”不是個好名字。你應該很少使用它。使用不會在每個表中重複的有意義的標識符。一旦你加入了幾個表(這是你在 SQL 中一直做的事情),你最終會得到多個名為“name”的列,並且必須處理列別名才能使用它。“id”或“code”同樣是不好的選擇。
使用如下建議的描述性標識符。
- 使用
doctor.code
and是一種反模式practice.doctor_code
。一些不太聰明的 ORM 習慣於使用它——這並不是一個好主意。除了“程式碼”是一個錯誤的標識符之外,對具有相同數據的列使用*相同的名稱是一種很好的做法。*兩個地方都用。或者更好的是:,因為列中的內容可能是“標識符”而不是“程式碼”(錯誤術語)。這樣的命名約定還允許在連接中使用方便的構造。doctor_code
doctor_id
USING
- 使用 SQL 標準**
<>
**而不是等效的!=
.- 使用表別名來縮短程式碼並保持可讀性。
所有東西放在一起,它可能看起來像這樣:
SELECT p.practice, d.name -- for a person, "name" is halfway sensible FROM doctor d JOIN practice p USING (doctor_id) WHERE d.name LIKE '%son' AND d.doc_type <> 'surgeon';
這些括號都不是必需的。
內部連接的效率是相同的(只要您在 下
join_collapse_limit
)。對於大於 PostgreSQL 的連接重新排序限制的連接列表,ON
謂詞中的額外項可能會更快。專注於風格。它在邏輯上是連接一個表到另一個表的條件的一部分嗎?把它放在
ON
謂詞中。是無關的嗎?把它放在WHERE
子句中。