MySQL联结

本文深入解析SQL中的联结概念,涵盖等值联结、自联结、自然联结及外部联结,阐述如何通过主键与外键实现数据表的有效连接,同时探讨了联结在查询效率与数据完整性的平衡策略。

总结

1. 联结方式有等值联结、自联结、自然联结和外联结。注意使用哪种联结。

2. 一定要标注联结条件,否则返回值不正确,得到笛卡尔积。

3. 注意联结的性能。

 

联结的通俗理解:把几个不同的表通过相同的列连接起了得到一个表,或者把其中几列取出来。联结不是物理实体,在数据库中不存在这个表,只存在于查询的执行中。

 

一、了解联结前需掌握一些基础知识

主键(Primary Key)&外键(Foreign Key)

主键是唯一的标识,不会变化,如供应商的ID。当信息有所改变时,主键也不会改变。

外键是其他表中的一列,包含了另一个表的主键。

外键可避免储存重复信息,且相关表中的信息更新不影响外键。

 

联结通过主键和外键实现!

可伸缩性:能够适应不断增加的工作量而不失败。

必须使用完全限定列名!如果不使用会出现笛卡尔积(Cartesian Product)的情况,或称叉联结(Cross Join)

 

二、联结方法:

  1. 等值联结(又称内部联结)
  2. 自联结
  3. 自然联结
  4. 外部联结

 

1. 等值联结(又称内部联结)基于两个表的相等测试。

有两种语法来明确指定联结的类型。

    1. WHERE

SELECT vend_name, prod_name, prod_price FROM vendors,products WHERE vendors.vend_id= products.vend_id ORDER BY prod_name, vend_name;

    1. INNER JOIN IN

SELECT vend_name, prod_name, prod_price FROM vendors INNER JOIN products ON vendors.vend_id= products.vend_id ORDER BY prod_name, vend_name;

两种语法是等价的,但是基于性能考虑,一般使用INNER JOIN ON的语法

注意,使用完全限定列名!

另外上篇博客中,子查询的语句可通过联结代替。用联结查询得到的结果与子查询一致。

地址:https://blog.youkuaiyun.com/m0_38061639/article/details/82872705

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='TNT2';

联结时,还可联结多个表,语句同上。

联结时注意性能,不要联结不必要的表

2. 自联结

首先引进表别名。可缩短SQL语句,允许在单条SQL语句中多次使用相同的表。

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

SELECT c.cust_name FROM customers AS c;

选出产品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';

上述查询还可用子查询,实践过程中可以两种都试一下,看哪种方法比较快。

3. 自然联结

相对于等值联结,自然联结中不包括重复的列。

4. 外部联结

下图即以左侧表—customers中的顾客id为准,看其对应有哪几个订单order_num。

顾客表:保存所有顾客信息

订单表:保存订单id和对应下单顾客id

进行外部联结操作,以每个顾客为基准,看顾客下的订单。可以看出用户10002并没有下过订单。

SELECT customers.cust_id, orders.order_num FROM customers LEFT OUTER JOIN orders ON customers.cust_id=orders.cust_id;

也可使用RIGHT OUTER JOIN,用法和LEFT OUTER JOIN一致,主要看想要以哪个表为基准

 

三、使用带聚合函数的联结

如:检索每个顾客的订单数

SELECT customers.cust_name, customers.cust_id, COUNT(customers.cust_id) AS num_ord

FROM customers

INNER JOIN orders

ON customers.cust_id=orders.cust_id

GROUP BY customers.cust_id;

联结三个表:看每个顾客下的订单中的产品数量总和,则涉及三个表:customers,orders,和orderitems。

SELECT customers.cust_name, customers.cust_id, SUM(orderitems.order_item) AS num_ord

FROM customers, orders,orderitems

WHERE customers.cust_id=orders.cust_id

AND orders.order_num=orderitems.order_num

GROUP BY customers.cust_id;

 

### MySQL 自连接用法及示例 在MySQL中,自连接是一种特殊的表连接方式,它允许将一个表与其自身进行关联,从而实现对同一表中不同行之间的数据进行比较或计算。这种技术通常用于处理时间序列数据、层级结构数据或需要对相邻行进行操作的场景。 在自连接中,需要为表指定两个不同的别名,并通过适当的条件将它们关联起来。例如,可以使用`LEFT JOIN`或`INNER JOIN`来实现自连接。以下是两个常见的应用场景及其示例。 --- #### 查询每个月的销售额与前一个月的差值 此查询用于计算每个月的销售额与上个月的差值,从而分析销售额的变化趋势。通过自连接,可以将当前月的数据与上个月的数据进行关联: ```sql SELECT A.month AS 月份, A.revenue AS 当前月销售额, B.revenue AS 前一个月销售额, A.revenue - B.revenue AS 差值 FROM sales AS A LEFT JOIN sales AS B ON A.month = B.month + 1; ``` 在上述查询中,`A`和`B`是`sales`表的两个别名,通过`A.month = B.month + 1`的条件将当前月与上个月的数据进行匹配。如果某个月没有前一个月的数据(如第一个月),则`B.revenue`会返回`NULL`,差值也会显示为`NULL` [^1]。 --- #### 查询截止到每个月的累计销售额 此查询用于计算每个月的累计销售额,即从第一个月到当前月的总和。通过自连接和`GROUP BY`语句,可以实现这一功能: ```sql SELECT A.month AS 月份, SUM(B.revenue) AS 累计销售额 FROM sales AS A JOIN sales AS B ON A.month >= B.month GROUP BY A.month; ``` 在上述查询中,`A`和`B`再次作为`sales`表的别名。通过`A.month >= B.month`的条件,确保每个月的累计值包括所有之前月份的销售额。然后使用`SUM(B.revenue)`对匹配的记录进行求和,并通过`GROUP BY A.month`将结果按月份分组 [^1]。 --- 自连接的应用场景远不止于此,它还可以用于处理树形结构数据(如组织架构、分类树等),以及计算相邻行之间的差异(如股票价格变动、库存变化等)。使用自连接时需要注意以下几点: - 表必须具有能够唯一标识每一行的字段,如`month`或`id`。 - 自连接可能会导致数据膨胀,尤其是当连接条件不严格时,应尽量优化查询逻辑。 - 在使用`LEFT JOIN`时,需考虑缺失数据的情况,避免出现错误的计算结果。 --- ### 相关问题 1. 如何在MySQL中使用窗口函数替代自连接实现累计求和? 2. 自连接与子查询在性能上有何差异,如何优化? 3. 如何在MySQL中实现树形结构数据的查询? 4. 自连接是否可以与其他表连接结合使用?如何实现多表关联? 5. 如何处理自连接中出现的重复数据问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值