读书笔记--SQL必知必会13--创建高级联结

13.1 使用表别名

SQL可以对列名、计算字段和表名起别名。

  • 缩短SQL语句
  • 允许在一条SELECT语句中多次使用相同的表。

注意:表别名只在查询执行中使用,不返回到客户端。

MariaDB [sqlbzbh]> SELECT cust_name,cust_contact
    -> FROM Customers AS C, Orders AS O, OrderItems AS OI
    -> WHERE C.cust_id = O.cust_id
    -> AND OI.order_num = O.order_num
    -> AND prod_id = 'RGAN01';
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set (0.01 sec)

MariaDB [sqlbzbh]> 

13.2 使用不同类型的联结

除了内联结(等值联结)之外,还有自联结(self-join),自然联结(natural join)和外联结(outer join)。

13.2.1 自联结

自联结通常作为外部语句,用来替代从相同表中检索数据的子查询语句。

MariaDB [sqlbzbh]> SELECT cust_id, cust_name, cust_contact FROM Customers WHERE cust_name = (SELECT cust_name FROM Customers WHERE cust_contact = 'Jim Jones');
+------------+-----------+--------------------+
| cust_id    | cust_name | cust_contact       |
+------------+-----------+--------------------+
| 1000000003 | Fun4All   | Jim Jones          |
| 1000000004 | Fun4All   | Denise L. Stephens |
+------------+-----------+--------------------+
2 rows in set (0.01 sec)

MariaDB [sqlbzbh]> 
MariaDB [sqlbzbh]> SELECT c1.cust_id, c1.cust_name, c1.cust_contact
    -> FROM Customers AS c1, Customers AS c2
    -> WHERE c1.cust_name = c2.cust_name
    -> AND c2.cust_contact = 'Jim Jones';
+------------+-----------+--------------------+
| cust_id    | cust_name | cust_contact       |
+------------+-----------+--------------------+
| 1000000003 | Fun4All   | Jim Jones          |
| 1000000004 | Fun4All   | Denise L. Stephens |
+------------+-----------+--------------------+
2 rows in set (0.00 sec)

MariaDB [sqlbzbh]> 

13.2.2 自然联结

自然联结排除相同列多次出现,使每一列只返回一次。
自然联结一般由客户自己来完成,只选择那些唯一的列。也可以通过对一个表使用通配符(SELECT *),而对其他的表使用明确的子集来完成。
事实上,目前为止所用到的每个内联结都是自然联结。

MariaDB [sqlbzbh]> SELECT C.*, O.order_num, O.order_date, OI.prod_id, OI.quantity, OI.item_price
    -> FROM Customers AS C, Orders AS O, OrderItems AS OI
    -> WHERE C.cust_id = O.cust_id
    -> AND OI.order_num = O.order_num
    -> AND prod_id = 'RGAN01';
+------------+---------------+---------------------+-----------+------------+----------+--------------+--------------------+-----------------------+-----------+---------------------+---------+----------+------------+
| cust_id    | cust_name     | cust_address        | cust_city | cust_state | cust_zip | cust_country | cust_contact       | cust_email            | order_num | order_date          | prod_id | quantity | item_price |
+------------+---------------+---------------------+-----------+------------+----------+--------------+--------------------+-----------------------+-----------+---------------------+---------+----------+------------+
| 1000000004 | Fun4All       | 829 Riverside Drive | Phoenix   | AZ         | 88888    | USA          | Denise L. Stephens | dstephens@fun4all.com |     20007 | 2012-01-30 00:00:00 | RGAN01  |       50 |       4.49 |
| 1000000005 | The Toy Store | 4545 53rd Street    | Chicago   | IL         | 54545    | USA          | Kim Howard         | NULL                  |     20008 | 2012-02-03 00:00:00 | RGAN01  |        5 |       4.99 |
+------------+---------------+---------------------+-----------+------------+----------+--------------+--------------------+-----------------------+-----------+---------------------+---------+----------+------------+
2 rows in set (0.00 sec)

MariaDB [sqlbzbh]> 

13.2.3 外联结

外联结包含了那些在相关表中没有关联的行。
在使用OUTER JOIN语法时,必须使用RIGHT或者LEFT关键字指定包括其所有行的表。
RIGHT --- OUTET JOIN 右边的表;LEFT --- OUTET JOIN 左边的表。
也可以理解为,外联结分为左外联结和右外联结两种基本形式。

全外联结(full outer join),检索两个表中的所有行并关联。注意,很多版本的DBMS并不支持全外联结。

内联结

MariaDB [sqlbzbh]> SELECT Customers.cust_id, Orders.order_num
    -> FROM Customers INNER JOIN Orders
    -> ON Customers.cust_id = Orders.cust_id;
+------------+-----------+
| cust_id    | order_num |
+------------+-----------+
| 1000000001 |     20005 |
| 1000000001 |     20009 |
| 1000000003 |     20006 |
| 1000000004 |     20007 |
| 1000000005 |     20008 |
+------------+-----------+
5 rows in set (0.00 sec)

MariaDB [sqlbzbh]> 

外联结

MariaDB [sqlbzbh]> SELECT Customers.cust_id, Orders.order_num
    -> FROM Customers LEFT OUTER JOIN Orders
    -> ON Customers.cust_id = Orders.cust_id;
+------------+-----------+
| cust_id    | order_num |
+------------+-----------+
| 1000000001 |     20005 |
| 1000000001 |     20009 |
| 1000000002 |      NULL |
| 1000000003 |     20006 |
| 1000000004 |     20007 |
| 1000000005 |     20008 |
+------------+-----------+
6 rows in set (0.00 sec)

MariaDB [sqlbzbh]>
MariaDB [sqlbzbh]> SELECT Customers.cust_id, Orders.order_num FROM Customers RIGHT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;
+------------+-----------+
| cust_id    | order_num |
+------------+-----------+
| 1000000001 |     20005 |
| 1000000001 |     20009 |
| 1000000003 |     20006 |
| 1000000004 |     20007 |
| 1000000005 |     20008 |
+------------+-----------+
5 rows in set (0.00 sec)

MariaDB [sqlbzbh]> 

13.3 使用带聚集函数的联结

聚集函数可以与联结一起使用。

MariaDB [sqlbzbh]> SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord
    -> FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id
    -> GROUP BY Customers.cust_id;
+------------+---------+
| cust_id    | num_ord |
+------------+---------+
| 1000000001 |       2 |
| 1000000003 |       1 |
| 1000000004 |       1 |
| 1000000005 |       1 |
+------------+---------+
4 rows in set (0.01 sec)

MariaDB [sqlbzbh]> 
MariaDB [sqlbzbh]> SELECT Customers.cust_id, COUNT(Orders.order_num) AS num_ord
    -> FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id
    -> GROUP BY Customers.cust_id;
+------------+---------+
| cust_id    | num_ord |
+------------+---------+
| 1000000001 |       2 |
| 1000000002 |       0 |
| 1000000003 |       1 |
| 1000000004 |       1 |
| 1000000005 |       1 |
+------------+---------+
5 rows in set (0.00 sec)

MariaDB [sqlbzbh]> 

13.4 使用联结和联结条件

  • 注意联结类型,虽然一般情况下都是用内联结。
  • 不同的DBMS对联结语法的定义不同。
  • 确保并提供正确的联结条件,否则会返回不正确的数据或笛卡尔积。
  • 测试包含多个联结的语句前,应该分别测试每个联结。
posted @ 2016-12-27 22:53  Anliven  阅读(266)  评论(0编辑  收藏  举报