8、联结表

Posted by CodingWithAlice on July 11, 2022

8、联结表

阅读书籍《SQL必知必会(第4版)》笔记

关系表:把信息分解成多个表,一类数据一个表。

联结:是一种机制,用来在一条 SELECT 语句中关联表,因此称为联结。

解决的痛点:

  • 重复信息存储,浪费存储空间
  • 信息变更只需修改一次
  • 重复数据存储时,很难保证每次输入该数据的方式相同,不一致的数据在报表中就很难利用

1、创建联结

等值联结/内联结:指定要联结的所有表,及关联他们的方式即可

  • 或者使用关键词 INNER JOIN+ON
SELECT vend_name, prod_name, prod_price # 三个属性,来源于两个表
FROM Vendors, Products 
WHERE Vendors.vend_id = Products.vend_id # 联结、匹配指定

-- INNER JOIN + ON
SELECT vend_name, prod_name, prod_price
FROM Vendors INNER JOIN Products 
ON Vendors.vend_id = Products.vend_id

-- 三个表联结
SELECT vend_name, prod_name, prod_price, quantity
FROM Vendors, Products, OrderItems
WHERE Vendors.vend_id = Products.vend_id
	AND OrderItems.prod_id = Products.prod_id
	AND order_num = 2025; # 订单号为 2025 的物品

2、高级联结

  • 使用表别名(只在查询时使用,不返回到客户端)
SELECT cust_name, cust_contact
FROM Customers AS C, Orders AS O, OrderItems AS OI # 别名
WhERE C.cust_id = O.cust_id
	AND O.order_num = OI.order_num
	AND prod_id = 'gran01';
  • 自联结:同一张表可以有多个别名用于筛选
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 = 'Alice Qiu'; # 查询指定联系人的公司的所有联系人的练习方式
  • 自然联结:要求只能选择那些唯一的列(一般都是自然连接,不会有重复的列被筛选出来)
SELECT C.*, O.order_num, O.order_date, # 只有C表是通配符
	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 = 'rgna01';
  • 外联结:包含了那些在相关表中没有关联的行
    • 必须使用 LEFT 或者 RIGHT关键词指定包含其所有行的表
SELECT Customers.cust_id, Orders.order_num
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;
-- 结果
cust_id order_num
100001  20005
100002  20009
100003  (NULL) # 检索没有订单顾客在内的所有顾客
100004  20008

-- 如果上述查询 sql 中的 LEFT OUTER 外联结换成 INNER JOIN 内联结,会筛选出有订单顾客
-- 结果
cust_id order_num
100001  20005
100002  20009
100004  20008
  • 全外联结:包含了两个表所有不关联的行 -> FULL OUTER JOIN
在联结中使用 聚集函数
# 检索所有顾客及每个顾客下的订单数
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; # 按顾客分组
关键词 UNOIN 组合查询

把输出组合成一个查询结果集 -> 可以简化 WHERE 子句

  • 1、每个查询必须包含相同的列、表达式、聚集函数
  • 2、查询结果中自动去除重复的行(如果想要返回所有的匹配行,可以使用 UNION ALL 而不是 UNION)
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION # 组合了上下两次查询
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Full4';

-- 上面的组合可以写成 -> 查询得到的结果是一样的,但是每一行顺序是不同的
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
	OR cust_name = 'Full4';