《SQL必知必会》笔记6-子查询、联结表join

1 使用子查询

查询(query):任何SQL语句都是查询,但一般指SELECT语句。

SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。

1.1 利用子查询进行过滤

在使用GROUP BY子句前,需要知道一些重要的规定。

订单存储在连个表中。每个订单包含订单编号、顾客ID、订单日期,在Orders表中存储为一行,各订单的物品存储在相关的OrderItems表中。Orders表不存储顾客信息,只存储顾客ID。顾客的实际信息存储在Customers表中。

现在,假如需要列出订购物品RGAN01的所有顾客,应该怎样检索?下面列出具体的步骤。

  • 检索包含物品RGAN01的所有订单的编号。
  • 检索具有前一步骤列出的订单的所有顾客的ID。
  • 检索前一步骤返回的所有顾客ID的顾客信息。

3小步:

SELECT order_num 
FROM OrderItems
WHERE prod_id = 'RGAN01';

SELECT cust_id 
FROM Orders
WHERE order_num IN (20007, 20008);

SELECT cust_name, cust_contact 
FROM Customers
WHERE cust_id IN ('1000000004', '1000000005');
《SQL必知必会》笔记6-子查询、联结表join_第1张图片
《SQL必知必会》笔记6-子查询、联结表join_第2张图片
《SQL必知必会》笔记6-子查询、联结表join_第3张图片

一步搞定:

SELECT cust_name, cust_contact 
FROM Customers
WHERE cust_id IN ( SELECT cust_id 
                   FROM Orders
                   WHERE order_num IN ( SELECT order_num 
                                        FROM OrderItems
                                        WHERE prod_id = 'RGAN01'));
《SQL必知必会》笔记6-子查询、联结表join_第4张图片

为了执行上述SELECT语句,DBMS实际上必须执行三条SELECT语句。最里边的子查询返回订单号列表,此列表用于其外面的子查询的WHERE子句。外面的子查询返回顾客ID列表,此顾客ID列表用于最外层查询的WHERE子句。最外层查询返回所需的数据。

可见,在WHERE子句中使用子查询能够编写出功能很强且很灵活的SQL语句。对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。

注意:作为子查询的SELECT语句只能查询单个列。企图检索多个列将返回错误。


1.2 作为计算字段使用子查询

使用子查询的另一个方法是创建计算字段。

假如需要显示Customers表中每个顾客的订单总数。订单与相应的顾客ID存储在Orders表中。

执行这个操作,要遵循下面的步骤:

  1. 从Customers表中检索顾客列表。
  2. 对于检索出的每个顾客,统计其在Orders表中的订单数目。
SELECT cust_name, cust_state,
       ( SELECT COUNT(*) 
         FROM Orders
         WHERE Orders.cust_id = Customers.cust_id ) AS orders
FROM Customers
ORDER BY cust_name;
《SQL必知必会》笔记6-子查询、联结表join_第5张图片

这里要采用完全限定列名,一个在Customers中,另一个在Orders中。

比较的是Orders表中的cust_id和当前正从Customers表中检索的cust_id:WHERE Orders.cust_id = Customers.cust_id。

如果不采用完全限定列名,会返回错误的结果。

SELECT cust_name, cust_state,
       ( SELECT COUNT(*) 
         FROM Orders
         WHERE cust_id = cust_id ) AS orders
FROM Customers
ORDER BY cust_name;
《SQL必知必会》笔记6-子查询、联结表join_第6张图片

2 联结表JOIN

2.1 联结join

关系表的设计就是要把信息分解成多个表,一类数据一个表,各表通过某些共同的值互相关联(所以才叫关系数据库)。

如果数据存储在多个表中,怎样用一条SELECT语句就检索出数据呢?答案就是使用联结。

简单说,联结是一种机制,用来在一条SELECT语句中关联表,因此称为联结。使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。


2.2 创建联结

创建联结很简单,指定要联结的所有表以及关联它们的方式即可。

SELECT vend_name, prod_name, prod_price
FROM Vendors, Products
WHERE Vendors.vend_id = Products.vend_id;
《SQL必知必会》笔记6-子查询、联结表join_第7张图片

在一条SELECT语句中联结几个表时,相应的关系是在运行中构造的。在联结两个表时,实际要做的事将第一个表中的每一行与第二个表中的每一行配对。WHERE子句作为过滤条件,只包含那些匹配给定条件(这里是联结条件)的行。没有WHERE子句的话,第一个表中的每一行将与第二个表中的每一行配对,而不管它们逻辑上是否能陪在一起。

SELECT vend_name, prod_name, prod_price
FROM Vendors, Products;
《SQL必知必会》笔记6-子查询、联结表join_第8张图片

返回的数据用每个供应商匹配了每个产品,包括了供应商不正确的产品。这些数据,显然不是我们想要的。


2.3 内联结(inner join)

目前为止,使用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内联结(inner join)。内联结是最常用的联结方式。

SELECT vend_name, prod_name, prod_price
FROM Vendors INNER JOIN Products
ON Vendors.vend_id = Products.vend_id;
《SQL必知必会》笔记6-子查询、联结表join_第9张图片

2.4 联结多个表

SELECT prod_name, vend_name, prod_price, quantity
FROM  OrderItems, Products, Vendors
WHERE Products.vend_id = Vendors.vend_id
AND OrderItems.prod_id = Products.prod_id
AND order_num = 20007;
《SQL必知必会》笔记6-子查询、联结表join_第10张图片

联结的表越多,性能下降越厉害。

使用子查询:

SELECT cust_name, cust_contact 
FROM Customers
WHERE cust_id IN ( SELECT cust_id 
                   FROM Orders
                   WHERE order_num IN ( SELECT order_num  
                                        FROM OrderItems
                                        WHERE prod_id = 'RGAN01'));
《SQL必知必会》笔记6-子查询、联结表join_第11张图片

联结查询:

SELECT cust_name, cust_contact 
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id
AND OrderItems.order_num = Orders.order_num
AND prod_id = 'RGAN01';
《SQL必知必会》笔记6-子查询、联结表join_第12张图片

如果您发现文中有不清楚或者有问题的地方,请在下方评论区留言,我会根据您的评论,更新文中相关内容,谢谢!

你可能感兴趣的:(《SQL必知必会》笔记6-子查询、联结表join)