博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2.6. PostgreSQL表之间连接
阅读量:5316 次
发布时间:2019-06-14

本文共 2993 字,大约阅读时间需要 9 分钟。

到目前为止,我们的查询一次只访问了一个表。查询可以一次访问多个表,或者用某种方式访问一个表,而同时处理该表的多个行。一个同时访问同一个或者不同表的多个行的查询叫连接查询。举例来说,比如你想列出所有天气记录以及这些记录相关的城市。要实现这个目标,我们需要拿 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 表里的不匹配行。我们稍后将看到如何修补这个问题。

  • 有两个字段包含城市名。这是正确的,因为 weathercities 表的字段是接在一起的。不过,实际上我们不想要这些,因此你将可能希望明确列出输出字段而不是使用 *

    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_lotemp_hi 字段与 weather 表里其它行的 temp_lotemp_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 表重新标记为 W1W2 以区分连接的左边和右边。你还可以用这样的别名在其它查询里节约一些敲键,比如:

SELECT *    FROM weather w, cities c    WHERE w.city = c.name;

以后会经常碰到这样的缩写。

转载于:https://www.cnblogs.com/wolaiye320/p/5564209.html

你可能感兴趣的文章
Vue购物车项目
查看>>
jdbc 3.0
查看>>
java 流读写文件
查看>>
elk 数据存储
查看>>
api 跳转规则
查看>>
PHP计算多少秒/分/时/天/周/月/年之前 : timeago
查看>>
B-Boxes
查看>>
Cannot access org.springframework.context.ConfigurableApplicationContext
查看>>
二分图最大匹配
查看>>
为什么抽象类不能实例化却有构造方法
查看>>
UESTC 电子科大专题训练 DP-D
查看>>
活代码LINQ——06
查看>>
软件配置管理
查看>>
Springboot 常见注解的使用方法(一)
查看>>
Linq to Entity经验:表达式转换(修正版本)
查看>>
安全运维
查看>>
0002---五层小山
查看>>
apache+php+mysql服务器环境配置注意点
查看>>
Vue-footer始终置底
查看>>
bitVector@ java bit自我practice##Q&A:为何int 来初始化size of bitVector?long,甚至是BigInteger等策略...
查看>>