|
2.6. 在表之间连接到目前为止,我们的查询一次只访问了一个表. 查询可以一次访问多个表,或者用某种方式访问一个表,而同时处理该表的 多个行.一个同时访问同一个或者不同表的多个行的查询叫 连接(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)
观察结果集的两个方面∶
练习∶. 看看省略 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 表的字段.这种类型的查询叫 外连接(outer 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) 这个查询是一个 左手边外连接(left outer join) 因为在连接操作符(译注∶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; 你以后会经常碰到这样的缩写的. |