设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间17 现在时间17 缓存数据 这个世界上很多东西会变,很多人会走。 但你在我心里,从开始的那一天,到现在从来没有变过。 我一直在等,等你的消息。

这个世界上很多东西会变,很多人会走。 但你在我心里,从开始的那一天,到现在从来没有变过。 我一直在等,等你的消息。 -- 盛夏的果实

查看: 293|回复: 1

MySQL高级查询之JOIN、子查询、窗口函数实际案例

[复制链接]

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:23
  • 打卡月天数:0
  • 打卡总奖励:313
  • 最近打卡:2025-06-30 14:06:36
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
332
主题
294
精华
0
金钱
1276
积分
680
注册时间
2023-2-11
最后登录
2025-6-30

发表于 2025-5-26 22:37:38 | 显示全部楼层 |阅读模式
前言

在日常开发中,单表查询往往无法满足业务需求。通过高级查询技术,MySQL 能够灵活地从多个表中获取数据、进行复杂的数据筛选和分析。本文将重点介绍三种高级查询方式:JOIN(连接查询)子查询窗口函数,并提供实际案例帮助你更好地理解和应用这些技术。

1. JOIN(连接查询)

JOIN 允许我们在 SQL 语句中将两个或多个表通过相关联的列进行组合,从而在一条查询中获取多表数据。MySQL 中常见的 JOIN 类型包括:

1.1 内连接(INNER JOIN)


  • 原理:返回两个表中满足连接条件的记录。
  • 示例
    1. SELECT o.order_id, o.order_date, c.customer_name
    2. FROM orders AS o
    3. INNER JOIN customers AS c ON o.customer_id = c.customer_id;
    复制代码
    上述查询返回所有订单及其对应客户名称,仅当订单和客户存在匹配关系时才会返回结果。

1.2 左连接(LEFT JOIN)


  • 原理:返回左表的所有记录,即使右表中没有匹配也会显示 NULL。
  • 示例
    1. SELECT c.customer_name, o.order_id
    2. FROM customers AS c
    3. LEFT JOIN orders AS o ON c.customer_id = o.customer_id;
    复制代码
    此查询列出所有客户,即使有些客户没有订单,相关订单字段将显示为 NULL。

1.3 右连接(RIGHT JOIN)


  • 原理:与左连接类似,不过返回右表所有记录,左表未匹配部分显示 NULL。
  • 示例
    1. SELECT o.order_id, c.customer_name
    2. FROM orders AS o
    3. RIGHT JOIN customers AS c ON o.customer_id = c.customer_id;
    复制代码
    这种连接方式在实际开发中较少使用,多数场景可以通过调整 LEFT JOIN 的顺序来实现相同效果。

1.4 自连接(Self JOIN)


  • 原理:同一张表中不同记录间的关联查询,通常用于查找具有层级或关系的数据。
  • 示例
    1. SELECT e1.employee_name AS Manager, e2.employee_name AS Subordinate
    2. FROM employees AS e1
    3. INNER JOIN employees AS e2 ON e1.employee_id = e2.manager_id;
    复制代码
    该查询展示了管理者与其下属之间的关系。

2. 子查询

子查询(Subquery)是嵌套在其他 SQL 语句内部的查询语句,通常用于将一个查询的结果作为条件或数据源。根据使用位置,子查询可分为以下几种:

2.1 标量子查询


  • 特点:返回单个值,可以在 WHERE 或 SELECT 子句中直接使用。
  • 示例
    1. SELECT order_id, order_date
    2. FROM orders
    3. WHERE customer_id = (SELECT customer_id FROM customers WHERE customer_name = '张三');
    复制代码
    此查询将客户名称为“张三”的客户 ID 提取出来,并用于过滤订单表中的记录。

2.2 列表子查询


  • 特点:返回一列值,可以用于 IN 或 NOT IN 条件中。
  • 示例
    1. SELECT order_id, order_date
    2. FROM orders
    3. WHERE customer_id IN (SELECT customer_id FROM customers WHERE city = '北京');
    复制代码
    该查询筛选出所有来自北京的客户的订单。

2.3 表子查询


  • 特点:返回一个结果集,通常用于 FROM 子句中充当临时表。
  • 示例
    1. SELECT t.customer_id, t.total_orders
    2. FROM (
    3.     SELECT customer_id, COUNT(*) AS total_orders
    4.     FROM orders
    5.     GROUP BY customer_id
    6. ) AS t
    7. WHERE t.total_orders > 5;
    复制代码
    这里的子查询先统计每个客户的订单数量,再过滤出订单数大于 5 的客户。

2.4 相关子查询


  • 特点:子查询依赖于外层查询的数据,每行记录都将执行一次子查询。
  • 示例
    1. SELECT e.employee_id, e.employee_name,
    2.        (SELECT COUNT(*) FROM orders o WHERE o.salesperson_id = e.employee_id) AS order_count
    3. FROM employees AS e;
    复制代码
    该查询为每个销售人员统计其负责的订单数量。

3. 窗口函数

MySQL 从 8.0 版本开始支持窗口函数(Window Functions),这使得在不使用子查询的情况下直接对查询结果进行分组统计、排名等操作成为可能。

3.1 常见窗口函数


  • ROW_NUMBER():为结果集中的每一行返回一个唯一的序号。
    1. SELECT order_id, order_date,
    2.        ROW_NUMBER() OVER (ORDER BY order_date) AS row_num
    3. FROM orders;
    复制代码
    该查询按照订单日期为每个订单分配一个行号。
  • RANK() 与 DENSE_RANK():用于排名,但在存在相同值时处理方式略有不同。RANK 会跳过排名,而 DENSE_RANK 不跳过。
    1. SELECT customer_id, total_spent,
    2.        RANK() OVER (ORDER BY total_spent DESC) AS rank
    3. FROM (
    4.     SELECT customer_id, SUM(amount) AS total_spent
    5.     FROM orders
    6.     GROUP BY customer_id
    7. ) AS spending;
    复制代码
  • SUM()、AVG()、MAX()、MIN() 等聚合函数:可以作为窗口函数使用,计算每个分组内的累计值或平均值等。
    1. SELECT order_id, order_date, amount,
    2.        SUM(amount) OVER (ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total
    3. FROM orders;
    复制代码
    上述查询展示了订单金额的累计总和,可以用于生成报表或趋势图。

3.2 使用场景


  • 排名和排序:对销售额、得分或其他指标进行排序和排名。
  • 累计求和:生成动态的累计值,如销售额的逐日累加。
  • 分区统计:在不使用 GROUP BY 的情况下,对数据进行分区统计,保留详细数据行。

4. 实际案例:综合应用

假设你需要生成一个销售报表,其中包含每个销售人员的订单总额及其在各自区域内的排名,可以结合子查询与窗口函数来实现:
  1. WITH SalesData AS (
  2.   SELECT salesperson_id, region, SUM(amount) AS total_sales
  3.   FROM orders
  4.   GROUP BY salesperson_id, region
  5. )
  6. SELECT salesperson_id, region, total_sales,
  7.        RANK() OVER (PARTITION BY region ORDER BY total_sales DESC) AS sales_rank
  8. FROM SalesData;
复制代码
这里,**CTE(公用表表达式)**先统计出每个销售人员在各个区域内的订单总额,然后使用窗口函数按区域进行分区并对总销售额进行排名,帮助管理者快速识别出每个区域的销售冠军。

5. 总结


  • JOIN 使得多表关联查询变得简单、高效,可以通过不同类型的连接满足各种业务需求。
  • 子查询 提供了灵活的数据筛选和过滤方式,适用于对单个数据项或整个结果集的处理。
  • 窗口函数 则在 MySQL 8.0 之后引入,为数据统计、排名和累计计算提供了更直观、更高效的解决方案。
通过深入掌握这三种高级查询技术,你可以大幅提升 MySQL 查询的复杂度与灵活性,从而更好地支持复杂业务场景和数据分析需求。欢迎在实践中不断尝试和优化,充分利用 MySQL 强大的数据处理能力!
到此这篇关于MySQL高级查询之JOIN、子查询、窗口函数的文章就介绍到这了,更多相关MySQL高级查询JOIN、子查询、窗口函数内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:常驻代表
  • 打卡总天数:30
  • 打卡月天数:0
  • 打卡总奖励:418
  • 最近打卡:2025-04-20 04:19:41
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
472
积分
68
注册时间
2023-3-22
最后登录
2025-4-20

发表于 3 天前 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表