创建高级联结——自联结、自然联结、外部联结&使用带聚集函数的联结

1.使用表别名

给表名起表名的好处有:

  1. 缩短SQL语句;
  2. 允许在单条SELECT语句中多次使用相同的表。

在这里插入图片描述

表别名不仅能用于where子句,它还可以用于select的列表、order by子句以及语句的其他部分。

但是,表别名只在查询执行中使用。与列别名不一样,表别名不返回到客户机。


2.使用不同类型的联结

2.1 自联结

自联结通常作为外部语句用来替代从相同表中检索数据时使用的子查询语句。虽然最终的结果是相同的,但有时候处理联结远比处理子查询快得多。
在这里插入图片描述
上述例子查询中需要的两个表实际上是相同的表,因此products表在from子句中出现了两次。虽然这是完全合法的,但对products的引用具有二义性,因为Mysql不知道你引用的是products表中的哪个实例。
为解决此问题,使用了表别名。products的第一次出现为别名p1,第二次出现为别名p2。where(通过匹配p1中的vend_id和p2中的vend_id)首先联结两个表,然后按第二个表中的prod_id过滤数据,返回所需的数据。


2.2 自然联结

自然联结排除多次出现,使每个列只返回一次。
在自然联结中,你只能选择那些唯一的列,通过对表使用通配符(select *),对所有其他表的列使用明确的子集来完成的。
在这里插入图片描述
在这个例子中,通配符只对第一个表使用。所有其他列明确列
出,所以没有重复的列被检索出来。
事实上,迄今为止我们建立的每个内部联结都是自然联结,很可能我们永远都不会用到不是自然联结的内部联结。


2.3 外部联结

在这里插入图片描述
如果使用外部联结,可以包括没有关联行的行,使用left outer join,因为customers表中包含所有客户id。在使用outer join语法时,必须使用right或left关键字指定包括其所有行的表(right指出的是outer join右边的表,而left指出的是outer join左边的表)。
在这里插入图片描述


3. 使用带聚集函数的联结

聚集函数也可以与联结一起使用。
在这里插入图片描述
在这里插入图片描述


4. 使用联结和联结条件

  1. 注意所使用的联结类型。一般我们使用内部联结,但使用外部联结也是有效的。
  2. 保证使用正确的联结条件,否则将返回不正确的数据。
  3. 应该总是提供联结条件,否则会得出笛卡儿积。
  4. 在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前,分别测试每个联结。这将使故障排除更为简单。

-- 使用表别名
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';
  
-- 自联结
-- 原来的子查询为:
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';
  
 -- 自然联结
 SELECT c.*, o.order_num, 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 = 'FB';

-- 内部联结,检索所有客户及其订单,显示不出没有订单的客户
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 RIGHT OUTER JOIN orders 
ON customers.`cust_id`= orders.`cust_id`;

-- 聚集函数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`;

-- 聚集函数count()与left outer join联结一起使用
SELECT customers.`cust_name`,
       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`;

猜你喜欢

转载自blog.csdn.net/weixin_49984044/article/details/108732832