到目前為止,我們的查詢一次只存取一個資料表。查詢可以一次存取多個資料表,或以同時處理資料表的多列的方式存取同一資料表。一次存取多個資料表(或同一資料表的多個實例)的查詢稱為join查詢。它們將一個資料表的列與第二個資料表的列組合,並使用表示式指定要配對的列。例如,若要傳回所有天氣記錄以及相關城市的位置,資料庫需要比較weather
資料表的每列的city
欄位與cities
資料表的所有列的name
欄位,並選擇這些值相符的列配對。[4]這將透過以下查詢完成
SELECT * FROM weather JOIN cities ON city = name;
city | temp_lo | temp_hi | prcp | date | name | location ---------------+---------+---------+------+------------+---------------+----------- San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53) San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53) (2 rows)
請注意結果集的兩件事
Hayward 城市沒有結果列。這是因為cities
資料表中沒有 Hayward 的相符項目,因此 join 會忽略weather
資料表中不相符的列。我們稍後會看到如何修正此問題。
有兩個欄位包含城市名稱。這是正確的,因為weather
和cities
資料表的欄位清單已串連。但實際上,這是不可取的,因此您可能會想明確列出輸出欄位,而不是使用*
SELECT city, temp_lo, temp_hi, prcp, date, location FROM weather JOIN cities ON city = name;
由於欄位都有不同的名稱,因此剖析器會自動找出它們屬於哪個資料表。如果兩個資料表中有重複的欄位名稱,您需要限定欄位名稱,以顯示您指的是哪個欄位,如下所示
SELECT weather.city, weather.temp_lo, weather.temp_hi, weather.prcp, weather.date, cities.location FROM weather JOIN cities ON weather.city = cities.name;
通常認為,在 join 查詢中限定所有欄位名稱是一種良好的樣式,這樣如果稍後將重複的欄位名稱新增到其中一個資料表,查詢就不會失敗。
到目前為止看到的 join 查詢也可以用這種形式編寫
SELECT * FROM weather, cities WHERE city = name;
此語法早於 SQL-92 中引入的JOIN
/ON
語法。資料表只是在FROM
子句中列出,比較表示式會新增到WHERE
子句。這種較舊的隱式語法和較新的顯式JOIN
/ON
語法的結果是相同的。但對於查詢的讀者來說,顯式語法使其含義更容易理解:join 條件由其自己的關鍵字引入,而以前該條件與其他條件混合在WHERE
子句中。
現在,我們將弄清楚如何將 Hayward 記錄取回。我們希望查詢執行的操作是掃描weather
資料表,並針對每一列尋找相符的cities
列。如果找不到相符的列,我們希望將一些「空值」取代為cities
資料表的欄位。這種查詢稱為外部 join。(到目前為止,我們看到的 join 是內部 join。)命令如下所示
SELECT * FROM weather LEFT OUTER JOIN cities ON weather.city = cities.name;
city | temp_lo | temp_hi | prcp | date | name | location ---------------+---------+---------+------+------------+---------------+----------- Hayward | 37 | 54 | | 1994-11-29 | | San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53) San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53) (3 rows)
此查詢稱為左外部 join,因為在 join 運算符號左側提及的資料表將在輸出中至少包含其每一列一次,而右側的資料表只會輸出與左側資料表的某些列相符的那些列。當輸出沒有右側資料表相符項的左側資料表列時,會將空值取代為右側資料表的欄位。
練習: 還有右外部 join 和完整外部 join。嘗試找出它們的作用。
我們也可以將一個資料表與其自身進行聯結,這稱為自聯結。舉例來說,假設我們想找出所有溫度範圍落在其他天氣紀錄範圍內的天氣紀錄。因此,我們需要將每個 weather
列的 temp_lo
和 temp_hi
欄位,與所有其他 weather
列的 temp_lo
和 temp_hi
欄位進行比較。我們可以透過以下查詢來達成:
SELECT w1.city, w1.temp_lo AS low, w1.temp_hi AS high, w2.city, w2.temp_lo AS low, w2.temp_hi AS high FROM weather w1 JOIN weather w2 ON w1.temp_lo < w2.temp_lo AND w1.temp_hi > w2.temp_hi;
city | low | high | city | low | high ---------------+-----+------+---------------+-----+------ San Francisco | 43 | 57 | San Francisco | 46 | 50 Hayward | 37 | 54 | San Francisco | 46 | 50 (2 rows)
在這裡,我們將 weather 資料表重新標記為 w1
和 w2
,以便區分聯結的左側和右側。您也可以在其他查詢中使用這種類型的別名,以節省一些輸入,例如:
SELECT * FROM weather w JOIN cities c ON w.city = c.name;
您會很頻繁地遇到這種縮寫方式。
如果您在文件中看到任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。