SQL 入门笔记(十三)创建高级联结
使用表别名
第 7 节介绍了如何使用别名引用被检索的表列,给列起别名的语法如下
1 | SELECT Concat(vend_name ,'(' , vend_country , ')') AS vend_title |
SQL 除了可以对列名和计算字段使用别名,还允许给表名起别名 ,这样做有两个理由
- 缩短 SQL 语句
- 允许在一条
SELECT
语句中多次使用相同的表
多次使用相同的表?是不是听上去很奇怪?别急,后面会有例子,但是先来尝试一下给表取别名
从上一篇的代码为例
1 | SELECT cust_name, cust_contact |
下面给表名取别名
1 | SELECT cust_name, cust_contact |
运行结果和上面是一样的,在这个例子中,别名只用于 WHERE
子句,但其实还可以用在 SELECT
、ORDER BY
以及其他部分。并且表别名只在查询执行中使用,与列别名不同,表别名不返回到客户端
注意:Oracle 中没有 AS
在 Oracle 中使用别名,不需要 AS
,简单地指定列名即可(因此,应该是 Customers C
,而不是 Customers AS C
使用不同类型的联结
自联结
如前所述,使用表别名的一个主要原因是能在一条 SELECT
语句中不止一次引用相同的表,下面是一个例子
假如要给与 Jim Jones 同一公司的所有顾客发送一封信件。这个查询需要首先找出 Jim Jones 工作的公司,然后找出在公司工作的顾客,下面是一种解决方法
1 | SELECT cust_id, cust_name, cust_contact # 鄙人按:cust_name 是公司名,cust_contact 应该是联系人名 |
现在来看看使用自联结的写法
1 | SELECT c1.cust_id, c1.cust_name, c1.cust_contact |
在此查询中需要的两个表实际上是相同的表,但是是有必要使用别名的,写的时候可以认为是复制出来了两张名字不同的表
自然联结
这部分我看得有点迷,书上讲的跟网上讲的也不一样,而且我感觉这东西没什么用(
1 | SELECT C.*, O.order_num, O.order_date, |
外联结
许多联结将表中的行与另一个表中的行相关联,但有时需要包含没有关联的那些行。例如,可能需要使用联结完成以下工作:
- 对每个顾客下的订单进行计数,包括那些至今尚未下单的顾客
- 列出所有产品以及订购数量,包括没有人订购的产品
- 计算平均销售规模,包括那些至今尚未下订单的顾客
注意:语法差别
创建外联结的语法在不同的 SQL 实现中可能稍有不同,下面的语法形式覆盖了大多数实现
先从一个内联结开始,它检索所有顾客及其订单
1 | SELECT Customers.cust_id, Orders.order_num |
外联结语法类似,要检索包括没有订单顾客在内的所有顾客,可如下进行
1 | SELECT Customers.cust_id, Orders.order_num |
类似于内联结,外联结使用 OUTER JOIN
来指定联结类型。与内连接关联两个表中的行不同的是,外联结还包含没有关联行的行。在使用 OUTER JOIN
时,必须使用 RIGHT
或者 LEFT
关键字指定那个表应该包含所有行。像这里,想要列出所有的顾客情况,而顾客表在左边,所有使用 LEFT
,又称为左联结,相对地,也有右联结
注意:SQLite 外联结
SQLite 支持 LEFT OUTER JOIN
,但是不支持 LEFT OUTER JOIN
,但这两个联结的不同也就只是顺序的区别,调换一下表的顺序即可
使用带聚集函数的联结
聚集函数用来汇总数据,但至今为止的例子都只是从一个表中汇总数据,其实聚集函数可以与联结一起使用
来看个例子,要检索所有顾客及每个顾客所下的订单数
1 | SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_order |
聚集函数还可以与其他联结一起使用
1 | SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord |