十三、使用子查询
1、子查询:嵌套在其他查询中的查询。
子查询总是从内向外处理。
1、利用子查询进行过滤。
例如:订单存储在两个表中其中orderitems表中存储各订单的物品。Orders表不存储客户信息,只存储客户的ID。Customers存储客户的信息。
先在要列出订购物品TNT2的所有客户。
SELECT cust_name, cust_contact
FROM customers
WHERE cut_id IN (SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id = ‘TNT2’));
2、作为计算字段使用子查询
十四、联结表
1、联结
联结的作用:联结是一种机制,用来在一条SELECT语句中关联表。
2、创建联结
联结的创建非常简单,规定要联结的所有的表以及它们如何关联即可
例如:SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name, prod_name;
等值联结(内部联结):基于两个表之间的相等测试。
这种联结也可以使用稍微不同的语法来实现
例如:SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
在这里,两个表之间的关系是FROM子句的组成部分,以INNER JOIN指定。在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出
联结多个表
SQL对一条SELECT语句中可以联结的表的数目没有限制。首先列出所有表,然后定义表之间的关系,WHERE后跟多个关系时,用AND连接。
例如:SELECT prod_name, vend_name, prod_price, quantity
FROM orderitems, products, vnedors
WHERE products.vend_id = vendors.vend_id
AND orderitems.prod_id = products.prod_id
AND order_num = 20005;
十五、创建高级联结
1、使用表别名
别名除了用于列名和计算字段外,SQL还允许给表名起别名。这样做有两大理由:
--缩短SQL语句
--允许在单条SELECT语句中多次使用相同的表
例如: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 = ‘TNT2’;
注意:表别名只在查询执行中使用。与列别名不一样,表别名不返回到客户机。
2、使用不同类型的联结
迄今为止我们使用的为内部联结或等值联结的简单联结。现在看其他三种联结,它们分别是自联结、自然联结和外部联结
(1)、自联结
使用表别名的主要原因之一是能在单条SELECT语句中不止一次引用相同的表。
例如:假如发现某物品(其ID为DTNTR)存在问题,因此想知道生产该物品的供应商生产的其他物品是否也存在问题。此查询要求首先招待生产ID为DTNTR的物品的供应商,然后找出这个供应商生产的其他物品。
方法一:使用子查询
SELECT prod_id, prod_name
FROM products
WHERE vend_id = (SELECT vend_id
FROM products
WHERE prod_id = ‘DTNTR’);
方法二、使用自联结
SELECT p1.prod_id, p1.prod_name
FROM products AS p1, products AS p2
WHERE p1.vend_id = p2.vend_id
AND p2.prod_id = ‘DTNTR’;
(2)、自然联结
自然联结排除多次出现,使每个列只返回一次。
迄今为止,我们建立的每个内部联结都是自然联结。
(3)、外部联结
外部联结:联结包含了那些在关联表中没有关联行的行。
例如:先给出一个内部联结,它检索所有客户及其订单
SELECT customers.cust_id, orders.order_num
FROM customers INNER JOIN orders
ON customers.cust_id = orders.cust_id;
下面给出外部联结。检索所有客户,包括那些没有订单的客户
SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;
这条SELECT语句使用了关键字OUTER JOIN来指定联结的类型。但是,与内部联结关联两个表中的行不同的是,外部联结还包括没有关联行的行。在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定其包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)
3、使用带聚集函数的联结
如果要检索所有客户及每个客户所下的订单数,下面使用了COUNT()函数的代码可完场工作。
SELECT customers.cust_name,
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;
此SELECT语句使用INNER JOIN将customers和orders表互相关联。
4、使用联结和联结条件
- 注意所使用的联结类型。一般我们使用内部联结,但使用外部联结也是有效的
- 应该总是提供联结条件,否则会得出笛卡儿积
- 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。
十六、组合查询
本章讲述如何利用UNION操作符将多条SELECT语句组合成一个结果集
1、组合查询
MySQL允许执行多个查询(多条SELECT语句),并将结果作为单个查询集返回。这些组合查询通常称为并或复合查询
需要使用组合查询的两种情况:
- 在单个查询中从不同的表返回类似结构的数据
- 对单个表执行多个查询,按单个查询返回数据
2、创建组合查询
可用UNION操作符来组合数条SQL查询。
UNION的使用很简单。所需要做的只是给出每条SELECT语句,在各条语句之间放上关键字UNION
例如:假设需要价格小于等于5的所有物品的一个列表,而且还想包括供应商1001和1002生产的所有物品(不考虑价格)
SELECT vend_id, prod_id, prod_price
FROM products
WHERE prod_price <= 5
UNION
SELECT vend_id, prod_id, prod_price
FROM products
WHERE vend_id IN (1001,1002);
UNION规则:
- UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔
- UNION中的每个查询必须包含相同的行、表达式或聚集函数(不过各个列不需要以形同的次序列出)
- 列数据类型必须兼容:兼容不必完全相同,但必须是DBMS可以隐含地转换的类型
包含或取消重复的行
使用UNION自动去除重复的行,如果要返回所有的行(包括重复的行)可使用UNION ALL
对组合查询结果排序
在用UNION组合查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。