?
This document uses PHP Chinese website manual Release
到目前為止,我們的查詢(xún)一次只訪(fǎng)問(wèn)了一個(gè)表。 查詢(xún)可以一次訪(fǎng)問(wèn)多個(gè)表,或者用某種方式訪(fǎng)問(wèn)一個(gè)表, 而同時(shí)處理該表的多個(gè)行。 一個(gè)同時(shí)訪(fǎng)問(wèn)同一個(gè)或者不同表的多個(gè)行的查詢(xún)叫連接查詢(xún)。 舉例來(lái)說(shuō),比如你想列出所有天氣記錄以及這些記錄相關(guān)的城市。 要實(shí)現(xiàn)這個(gè)目標(biāo), 我們需要拿weather表每行的city字段和 cities表所有行的name字段進(jìn)行比較, 并選取那些這些數(shù)值相匹配的行。
Note: 這里只是一個(gè)概念上的模型。 連接通常以比實(shí)際比較每個(gè)可能的配對(duì)行更高效的方式執(zhí)行,但這些是用戶(hù)看不到的。
這個(gè)任務(wù)可以用下面的查詢(xún)來(lái)實(shí)現(xiàn):
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)
觀察結(jié)果集的兩個(gè)方面:
沒(méi)有城市Hayward的結(jié)果行。 這是因?yàn)樵?tt class="STRUCTNAME">cities表里面沒(méi)有與Hayward匹配的行, 所以連接忽略了weather表里的不匹配行。 我們稍后將看到如何修補(bǔ)這個(gè)問(wèn)題。
有兩個(gè)字段包含城市名。這是正確的, 因?yàn)?tt class="STRUCTNAME">weather和cities表的字段是接在一起的。 不過(guò),實(shí)際上我們不想要這些, 因此你將可能希望明確列出輸出字段而不是使用*:
SELECT city, temp_lo, temp_hi, prcp, date, location FROM weather, cities WHERE city = name;
練習(xí): 看看省略WHERE子句的含義是什么。
因?yàn)檫@些字段的名字都不一樣, 所以分析器自動(dòng)找出它們屬于哪個(gè)表, 但是如果兩個(gè)表中有重復(fù)的字段名, 你就必須使用字段全稱(chēng)qualify你想要的字段:
SELECT weather.city, weather.temp_lo, weather.temp_hi, weather.prcp, weather.date, cities.location FROM weather, cities WHERE cities.name = weather.city;
一般認(rèn)為在連接查詢(xún)里使用字段全稱(chēng)是很好的風(fēng)格, 這樣,即使在將來(lái)向其中一個(gè)表里添加了同名字段也不會(huì)引起混淆。
到目前為止,這種類(lèi)型的連接查詢(xún)也可以用下面這樣的形式寫(xiě)出來(lái):
SELECT * FROM weather INNER JOIN cities ON (weather.city = cities.name);
這個(gè)語(yǔ)法并非像上面那個(gè)那么常用, 我們?cè)谶@里寫(xiě)出來(lái)是為了讓你更容易了解后面的主題。
現(xiàn)在我們將看看如何能把Hayward記錄找回來(lái)。 我們想讓查詢(xún)干的事是掃描weather表, 并且對(duì)每一行都找出匹配的cities表里面的行。 如果沒(méi)有找到匹配的行,那么需要一些"empty values"代替cities表的字段。 這種類(lèi)型的查詢(xún)叫 外連接(我們?cè)诖酥翱吹降倪B接都是內(nèi)連接)。 這樣的命令看起來(lái)像這樣:
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)
這個(gè)查詢(xún)是一個(gè)left outer join, 因?yàn)檫B接操作符左邊的表中的行在輸出中至少出現(xiàn)一次, 而右邊的表中的行只輸出那些與左邊的表有匹配的行。 如果輸出的左表中的行沒(méi)有右表中的行與其對(duì)應(yīng), 那么右表中的字段將填充為NULL 。
練習(xí): 還有右連接和全連接。試著找出來(lái)它們能干什么。
我們也可以把一個(gè)表和自己連接起來(lái)。 這叫self join。比如,假設(shè)我們想找出那些在其它天氣記錄的溫度范圍之外的天氣記錄。 這樣我們就需要拿weather 表里每行的temp_lo和temp_hi字段與 weather表里其它行的temp_lo和temp_hi字段進(jìn)行比較。 我們可以用下面的查詢(xún)實(shí)現(xiàn)這個(gè)目標(biāo):
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 表重新標(biāo)記為W1和W2以區(qū)分連接的左邊和右邊。 你還可以用這樣的別名在其它查詢(xún)里節(jié)約一些敲鍵,比如:
SELECT * FROM weather w, cities c WHERE w.city = c.name;
以后會(huì)經(jīng)常碰到這樣的縮寫(xiě)。