【MySQL】表的连接和复合查询

欢迎来到Cefler的博客😁

🕌博客主页:折纸花满衣

🏠个人专栏:MySQL


目录

👉🏻连接JOIN

在MySQL中,连接(JOIN)是用于从两个或多个表中检索相关行的强大工具。通过使用JOIN,你可以基于这些表之间的某些相关列之间的关系来组合这些表的行。以下是关于JOIN的详细解释和示例:

🌍 1. INNER JOIN(内连接)

INNER JOIN返回两个表中满足连接条件的所有行。只有在两个表中都存在匹配的行时,这些行才会出现在结果集中。

示例

假设我们有两个表:customersorders。我们想找出所有下过订单的客户及其订单详情。

sql 复制代码
SELECT customers.customer_name, orders.order_id, orders.order_date
FROM customers
INNER JOIN orders ON customers.customer_id = orders.customer_id;

在这个示例中,我们基于customer_id列将customers表和orders表连接在一起。结果集将包含所有下过订单的客户及其对应的订单ID和订单日期。

🌍 2. LEFT JOIN(左连接)

LEFT JOIN从左表中选择所有的行,以及右表中满足连接条件的行。如果右表中没有匹配的行,则结果中右表的部分将包含NULL值。

示例

假设我们想要列出所有客户,无论他们是否下过订单。

sql 复制代码
SELECT customers.customer_name, orders.order_id, orders.order_date
FROM customers
LEFT JOIN orders ON customers.customer_id = orders.customer_id;

在这个示例中,结果集将包含customers表中的所有客户。对于下过订单的客户,order_idorder_date列将包含相应的值;对于没有下过订单的客户,这些列将包含NULL值。

🌍 3. RIGHT JOIN(右连接)

RIGHT JOIN与LEFT JOIN相反,它从右表中选择所有的行,以及左表中满足连接条件的行。如果左表中没有匹配的行,则结果中左表的部分将包含NULL值。

注意:在实际应用中,RIGHT JOIN的使用相对较少,因为你可以通过调整表的顺序和使用LEFT JOIN来达到相同的效果。

🌍4. FULL JOIN(全连接)

FULL JOIN返回左表和右表中满足连接条件的所有行。如果某一边没有匹配的行,则结果中对应的一边将包含NULL值。但是,MySQL本身不支持FULL JOIN。不过,你可以通过组合LEFT JOIN和UNION来达到相同的效果。

示例(模拟FULL JOIN):

sql 复制代码
SELECT * FROM customers
LEFT JOIN orders ON customers.customer_id = orders.customer_id

UNION

SELECT * FROM customers
RIGHT JOIN orders ON customers.customer_id = orders.customer_id
WHERE customers.customer_id IS NULL;

🌍 5. 交叉连接(CROSS JOIN)

CROSS JOIN返回左表中的每一行与右表中的每一行的组合,也称为笛卡尔积。这通常不是一个常用的连接类型,但在某些情况下可能很有用。

示例

sql 复制代码
SELECT * FROM customers
CROSS JOIN orders;

🌍 注意事项:

  • 在使用JOIN时,确保连接条件正确,以避免返回错误或意外的结果。
  • 当连接多个表时,为了简化查询和提高可读性,可以为表指定别名。
  • 在涉及大量数据的查询中,注意性能优化。使用索引、调整查询逻辑和避免不必要的JOIN操作可以帮助提高性能。
  • 使用EXPLAIN命令来分析查询的执行计划,以便进行性能调优。

👉🏻子查询

🌍1. 子查询在SELECT子句中使用

子查询可以在SELECT子句中使用,以从其他表中检索值,并将其用作外部查询的一部分。

示例 :假设我们有两个表:customers(包含客户信息)和orders(包含订单信息)。我们想要列出每个客户的订单总数。

sql 复制代码
SELECT customer_name, 
       (SELECT COUNT(*) FROM orders WHERE orders.customer_id = customers.customer_id) AS order_count
FROM customers;

在这个示例中,子查询对于每个customers表中的客户都会执行一次,以计算其订单数量。

🌍2. 子查询在FROM子句中使用(内联视图或派生表)

示例:查找每个客户的订单总数。

sql 复制代码
SELECT c.customer_name, co.order_count
FROM customers c
JOIN (
    SELECT customer_id, COUNT(*) AS order_count
    FROM orders
    GROUP BY customer_id
) AS co ON c.customer_id = co.customer_id;

在这个示例中,内部子查询(派生表)首先计算每个客户的订单数,并将其作为临时结果集co。然后,外部查询将customers表与这个临时结果集连接,以检索每个客户的名称和订单总数。

🌍 3. 子查询在WHERE子句中使用

示例:查找价格高于平均价格的产品。

sql 复制代码
SELECT product_name, price
FROM products
WHERE price > (
    SELECT AVG(price)
    FROM products
);

在这个示例中,内部子查询计算产品的平均价格。然后,外部查询选择价格高于平均价格的产品。

注意事项:

  • 子查询可以返回单个值、一行值、一列值或一个表的结果集。
  • 子查询的性能可能因数据量和查询的复杂性而异。优化器会尝试有效地执行子查询,但有时可能需要手动调整查询以提高性能。
  • 使用子查询时,确保连接条件和外层查询的WHERE条件逻辑清晰,以避免不必要的计算或错误的结果。
  • 在某些情况下,可以使用JOIN代替子查询,以提高查询的性能和可读性。但是,子查询在某些场景中(如聚合函数和条件语句中)仍然非常有用。

👉🏻合并查询

UNIONUNION ALL 是 SQL 中用于合并两个或多个 SELECT 语句结果集的操作符。这两个操作符的主要区别在于它们如何处理重复的行。

🌍 UNION

UNION 操作符用于合并两个或多个 SELECT 语句的结果集,但不包括重复的行。也就是说,它会从所有 SELECT 语句的结果集中删除重复的行,然后返回唯一的行。

语法

sql 复制代码
SELECT column_name(s) FROM table1
UNION
SELECT column_name(s) FROM table2;

注意

  1. 所有的 SELECT 语句必须具有相同的列数。
  2. 这些列也必须具有相似的数据类型。
  3. 列的顺序必须相同。

示例

假设有两个表 employees1employees2,它们都有 nameage 列。如果我们想要获取两个表中所有不重复的员工名称,可以使用 UNION

sql 复制代码
SELECT name FROM employees1
UNION
SELECT name FROM employees2;

🌍 UNION ALL

UNION ALL 操作符与 UNION 类似,但它会返回所有行,包括重复的行。也就是说,它不会删除任何重复的行。

语法

sql 复制代码
SELECT column_name(s) FROM table1
UNION ALL
SELECT column_name(s) FROM table2;

示例

使用与上面相同的 employees1employees2 表,如果我们想要获取两个表中所有的员工名称(包括重复的名称),可以使用 UNION ALL

sql 复制代码
SELECT name FROM employees1
UNION ALL
SELECT name FROM employees2;

🌍 性能考虑

由于 UNION 需要删除重复的行,所以它的性能通常比 UNION ALL 差。如果你知道结果集中不会有重复的行,或者你想要包括重复的行,那么使用 UNION ALL 会更加高效。

🌍 其他注意事项

  • 在使用 UNIONUNION ALL 时,你可以对每个 SELECT 语句使用 ORDER BY 子句,但只能有一个 ORDER BY 子句,并且它必须位于最后一个 SELECT 语句之后。如果你想要对整个结果集进行排序,而不是对每个 SELECT 语句的结果集进行排序,那么你应该这样做。
  • 如果你想要对每个 SELECT 语句的结果集进行排序,并在合并后保留这些排序,那么你需要使用其他方法,如子查询或临时表。

如上便是本期的所有内容了,如果喜欢并觉得有帮助的话,希望可以博个点赞+收藏+关注🌹🌹🌹❤️ 🧡 💛,学海无涯苦作舟,愿与君一起共勉成长


相关推荐
!!!5257 分钟前
maven的生命周期
java·数据库·maven
Hello Dam32 分钟前
基于 FastExcel 与消息队列高效生成及导入机构用户数据
java·数据库·spring boot·excel·easyexcel·fastexcel
许仙在19971 小时前
【无标题】四类sql语句通用
数据库·sql·mysql·sqlserver
云浩舟2 小时前
Golang并发读取json文件数据并写入oracle数据库的项目实践
开发语言·数据库·golang
学会沉淀。2 小时前
Redis
数据库·redis·缓存
deadknight94 小时前
Oracle重启后业务连接大量library cache lock
数据库·oracle
万事可爱^4 小时前
【SQL】进阶知识 -- 删除表的几种方法(包含表内单个字段的删除方法)
数据库·hive·sql·oracle
非凡的世界4 小时前
关于 ThinkPHP 与 PostgreSQL 结合使用的一些要点
数据库·postgresql
fox08155 小时前
wsl2上mysql出现ip端口冲突问题
网络·数据库·tcp/ip·mysql·wsl
m0_672449605 小时前
MySQL高级(事务隔离界别)
数据库·mysql