第十四章 使用子查询
子查询作为WHERE子句的条件
有时候一条SELECT语句无法满足我们的需求,我们可以把一条SELECT语句的结果用于另外一条SELECT语句的WHERE子句,来实现复杂查询。
例如:我们想要获取订购物品TNT2的所有客户的名字和联系方式: 可以按照下图中的复杂查询实现:
(1) 查询包含物品TNT2的所有订单的编号。 (2) 根据订单编号查询所有客户的ID。 (3) 根据客户的ID查询名字和联系方式。
在WHERE子句中使用子查询能够编写出功能很强并且很灵活的 SQL语句。对于能嵌套的子查询的数目没有限制,不过在实际使用时由于 性能的限制,不能嵌套太多的子查询。
需要的注意的地方:
1.能嵌套的子查询的数目没有限制,不过在实际使用时由于 性能的限制,不能嵌套太多的子查询。
2.列必须匹配,在WHERE子句中使用子查询,应该保证SELECT语句具有与WHERE子句中相同数目的列。通常,子查询将返回单个列并且与单个列匹配,但如果需要也可以使用多个列。
3.子查询一般与IN操作符结合使用,但也可以用于测试等于(=)、 不等于(<>)等。
子查询结果作为计算字段
例如:我们想要在获取顾客的信息的同时,获取客户的订单数,可以使用子查询来实现,如下图所示: 当然这个需求也可以使用JOIN来实现
第十五章 连接表
有时候针对单表的查询无法满足我们的需求,我们需要连接多个表,返回一组输出。连接并不是物理实体,只是在查询时建立。
笛卡尔积
在进行连接查询时,如果不指定任何WHERE 条件,那么返回的结果会是笛卡尔积,会拿第一个表中的行数与第二个表中的所有行进行配对,最终总行数会是第一个表的行数乘以第二个表中的行数。
WHERE条件
如果指定了WHERE条件,得到的结果会是根据条件对笛卡尔积的结果进行筛选过滤后的结果。例如在这个例子中,指定了products表的vend_id与vendors表的vend_id相等作为筛选条件,这样,连接的结果就是拿vendors表的vend_id去products表中找相匹配的数据。
等值连接(内连接)
上面的这种连接其实是等值连接,可以用连接的语法来写,可以更加明确连接类型
连接多个表
一条SELECT语句可以连接的表的数量没有限制,可以连接多个表,进行查询
使用连接来替代子查询
之前通过子查询嵌套来完成多表查询,现在可以使用连接来实现
第十六章 创建高级联结
本章将讲解外连接,以及如何对被联结的表使用表别名和聚集函数。
使用表别名
除了可以对列,计算字段起别名以外,还可以对表起别名。主要有以下好处:
1.缩短SQL语句(有些表名太长,可以起短的别名)
2.允许在单条SELECT语句中多次使用相同的表(对表进行自连接查询时会需要多次使用相同的表,在下面有相应的例子说明)
除了上一章讲到的内部连接(等值连接)以为,还有自连接,自然连接,外部连接三种连接:
自连接
自连接指的是一张表对自身进行连接,进行信息查询。 例如: 某物品(其ID为DTNTR)存在问题,因此想知道生产该物 品的供应商生产的其他物品是否也存在这些问题。此查询要求首先找到 生产ID为DTNTR的物品的供应商,然后找出这个供应商生产的其他物品。 可以使用自连接的实现:
此查询中需要的两个表实际上是相同的表,因此products表在 FROM子句中出现了两次。虽然这是完全合法的,但对products 的引用具有二义性,所以使用表别名避免歧义。 当然解决上面的这个查询需求也可以使用子查询来实现,如下图所示:
外连接
内部连接会将一个表中的行与另一个表中的行想关联,有时候也需要包含不满足关联条件的那些行,这就是外连接。 例如: 这条SELECT语句使用了关键字OUTER JOIN来指定联结的类型(而不是在WHERE子句中指 定)。但是,与内部联结关联两个表中的行不同的是,外部联结还包括没 有关联行的行。在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字 指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT 指出的是OUTER JOIN左边的表)。上面的例子使用LEFT OUTER JOIN从FROM 子句的左边表(customers表)中选择所有行。
使用带聚集函数的连接 聚集函数也可以和连接结合起来使用。 在这个例子中,使用INNER JOIN将customers和orders表互相关联。GROUP BY子句按客户分组数据,因此,函数调用COUNT (orders.order_num)对每个客户的订单计数,将它作为num_ord返回。
注意事项:
1.注意所使用的联结类型。一般我们使用内部联结,但使用外部联 结也是有效的。
2.保证使用正确的联结条件,否则将返回不正确的数据。
3.应该总是提供联结条件,否则会得出笛卡儿积。
4.在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前,分别测试每个联结。这将使故障排除更为简单。