| PostgreSQL 8.0.0 中文文件(轉譯自 PostgreSQL 中國 製作的簡體中文版本) | ||||
|---|---|---|---|---|
| Prev | Fast Backward | Chapter 2. SQL 語言 | Fast Forward | Next |
到目前為止,我們的查詢一次只訪問了一個資料表。 查詢可以一次訪問多個資料表,或者用某種方式訪問一個資料表,而同時處理該資料表的多個行。 一個同時訪問同一個或者不同資料表的多個行的查詢叫連接(join)查詢。 舉例來說,比如您想列出所有天氣記錄以及這些記錄相關的城市。 要實現這個目標,我們需要拿 weather資料表每行的city 字串和cities資料表所有行的name字串進行比較, 並選取那些這些數值相匹配的行。
注意: 這裡只是一個概念上的模型。改連接通常以比實際比較每個可能的行配對更高效的方式執行, 但這些是用戶看不到的。
這個任務可以用下面的查詢來實現:
SELECT *
FROM weather, cities
WHERE 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的匹配行,所以連接忽略 weather資料表裡的不匹配行。我們稍後將看到如何修補這個毛病。
有兩個字串包含城市名字。這是正確的, 因為 weather 和 cities 資料表的字串是接在一起的。不過,實際上我們不想要這些, 因此您將可能希望明確列出輸出字串而不是使用 *:
SELECT city, temp_lo, temp_hi, prcp, date, location
FROM weather, cities
WHERE city = name;
練習:. 看看省略 WHERE 子句的語義是什麼。
因為這些字串的名字都不一樣,所以分析器自動找出它們屬於哪個資料表, 但是在連接查詢裡使用字串全稱是很好的風格:
SELECT weather.city, weather.temp_lo, weather.temp_hi,
weather.prcp, weather.date, cities.location
FROM weather, cities
WHERE cities.name = weather.city;
到目前為止,這種類型的連接查詢也可以用下面這樣的形式寫出來:
SELECT *
FROM weather INNER JOIN cities ON (weather.city = cities.name);這個語法並非像上面那個那麼常用,我們在這裡寫出來是為了讓您更容易瞭解後面的主題。
現在我們將看看如何能把Hayward記錄找回來。 我們想讓查詢幹的事是掃瞄 weather 資料表, 並且對每一行都找出匹配的 cities 資料表裡面的行。 如果我們沒有找到匹配的行,那麼我們需要一些"空值"代替cities資料表的字串。 這種類型的查詢叫外連接。 (我們在此之前看到的連接都是內部連接。)這樣的命令看起來像這樣:
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)這個查詢是一個左手邊外連接, 因為在連接操作符(譯注︰LEFT OUTER JOIN)左手邊的資料表中的行在輸出中至少要出現一次, 而在右手邊的行將只輸出那些與左手邊行有對應匹配的行。 如果輸出的左手邊資料表的行沒有對應匹配的右手邊資料表的行,那麼在右手邊行的字串將填充空(NULL)。
練習:. 還有右連接和全連接。試著找出來它們能幹什麼。
我們也可以把一個資料表和自己連接起來。這叫做自連接。 比如,假設我們想找出那些在其它天氣記錄的溫度範圍之外的天氣記錄。 這樣我們就需要拿 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, weather W2
WHERE 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, cities c
WHERE w.city = c.name;您以後會經常碰到這樣的縮寫的.