当前位置: 首页 > ai >正文

sql语句执行流程

SQL语句的完整执行顺序详解

SQL语句的逻辑书写顺序与实际执行顺序是不同的。理解这个执行顺序对于编写高效查询和优化性能至关重要。

一、SQL语句的书写顺序(我们写的顺序)

SELECT column1, column2, aggregate(column3)
FROM table1JOIN table2 ON table1.id = table2.id
WHERE condition1
GROUP BY column1, column2
HAVING aggregate(column3) > value
ORDER BY column1 ASC, column2 DESC
LIMIT offset, count;

二、SQL语句的实际执行顺序

  1. ​FROM 和 JOIN​​(确定数据来源)
  2. ​WHERE​​(行级过滤)
  3. ​GROUP BY​​(分组)
  4. ​HAVING​​(组级过滤)
  5. ​SELECT​​(选择列)
  6. ​DISTINCT​​(去重)
  7. ​ORDER BY​​(排序)
  8. ​LIMIT/OFFSET​​(分页)

三、详细执行步骤解释(以具体例子说明)

示例查询:

SELECT d.department_name,COUNT(e.employee_id) AS emp_count,AVG(e.salary) AS avg_salary
FROM departments dLEFT JOIN employees e ON d.department_id = e.department_id
WHERE e.hire_date > '2020-01-01'
GROUP BY d.department_name
HAVING COUNT(e.employee_id) > 5
ORDER BY avg_salary DESC
LIMIT 10;

执行步骤分解:

  1. ​FROM & JOIN 阶段​​(最先执行)

    FROM departments d
    LEFT JOIN employees e ON d.department_id = e.department_id
    • 先加载departments表所有数据
    • 然后执行LEFT JOIN,关联employees
    • 此时生成一个虚拟的中间结果集(包含两表所有列)
  2. ​WHERE 阶段​​(行级过滤)

    WHERE e.hire_date > '2020-01-01'
    • 对上一步的中间结果集进行过滤
    • 只保留hire_date大于2020-01-01的记录
    • 注意:WHERE在GROUP BY之前执行,所以不能使用聚合函数
  3. ​GROUP BY 阶段​​(分组)

    GROUP BY d.department_name
    • 将过滤后的数据按部门名称分组
    • 此时每个分组包含多条员工记录
  4. ​HAVING 阶段​​(组级过滤)

    HAVING COUNT(e.employee_id) > 5
    • 对分组后的结果进行过滤
    • 只保留员工数大于5的部门
    • 注意:HAVING可以使用聚合函数,WHERE不能
  5. ​SELECT 阶段​​(选择列)

    SELECT d.department_name,COUNT(e.employee_id) AS emp_count,AVG(e.salary) AS avg_salary
    • 现在才确定最终返回哪些列
    • 计算每个部门的员工数和平均薪资
    • 为结果列指定别名(emp_count, avg_salary)
  6. ​DISTINCT 阶段​​(去重)

    • 如果查询包含DISTINCT,在此阶段去重
    • 本例中没有DISTINCT
  7. ​ORDER BY 阶段​​(排序)

    ORDER BY avg_salary DESC
    • 使用SELECT阶段创建的别名排序
    • 按平均薪资降序排列
    • 注意:可以使用列别名,因为ORDER BY在SELECT之后执行
  8. ​LIMIT 阶段​​(分页)

    LIMIT 10
    • 只返回前10条记录
    • 最后执行的操作

四、关键注意事项

  1. ​执行顺序解释为什么WHERE不能使用SELECT别名​​:

    -- 错误示例
    SELECT column1 AS c1 FROM table WHERE c1 > 10;
    -- 正确写法
    SELECT column1 AS c1 FROM table WHERE column1 > 10;
    • WHERE执行时SELECT还没执行,所以不知道别名
  2. ​HAVING与WHERE的区别​​:

    -- WHERE过滤行(GROUP BY之前)
    -- HAVING过滤组(GROUP BY之后)
    SELECT dept, AVG(salary) 
    FROM employees 
    WHERE hire_date > '2020-01-01'  -- 先过滤员工
    GROUP BY dept 
    HAVING AVG(salary) > 5000;     -- 再过滤部门
  3. ​ORDER BY可以使用SELECT别名​​:

    SELECT column1 + column2 AS total 
    FROM table 
    ORDER BY total;  -- 合法

五、复杂查询的执行顺序示例

SELECT t1.name,COUNT(t2.order_id) AS order_count
FROM customers t1JOIN orders t2 ON t1.customer_id = t2.customer_id
WHERE t2.order_date BETWEEN '2023-01-01' AND '2023-12-31'AND t1.country = 'USA'
GROUP BY t1.name
HAVING COUNT(t2.order_id) >= 3
ORDER BY order_count DESC
LIMIT 5;

执行流程:

  1. customers表获取所有客户数据
  2. 关联orders表,通过customer_id匹配
  3. 过滤出2023年的订单且客户国家为USA的记录
  4. 按客户姓名分组
  5. 筛选出订单数≥3的客户组
  6. 计算每个客户的订单数
  7. 按订单数降序排序
  8. 只返回前5条记录




 

六:哪些操作会产生中间表

SELECT d.name, COUNT(e.id) 
FROM departments d
JOIN employees e ON d.id = e.dept_id  -- [中间表1] 两表连接结果
WHERE e.salary > 5000                 -- [中间表2] 过滤后结果
GROUP BY d.name                       -- [中间表3] 分组后结果
HAVING COUNT(e.id) > 10               -- [中间表4] 组过滤后结果
ORDER BY COUNT(e.id) DESC             -- [中间表5] 排序后结果
LIMIT 5;                              -- 最终结果
  1. ​LIMIT/OFFSET​​:

    • 只是从已有结果集中截取部分行
    • 不改变数据内容,不产生新中间表
  2. ​SELECT列选择​​:

    • 只是从中间结果集中投影部分列
    • 不改变行数据,只是减少列数
http://www.xdnf.cn/news/13062.html

相关文章:

  • 指令管理—弹幕/礼物/快捷键—抖音直播伴侣—使用教程
  • omi开源程序是AI 可穿戴设备的源码。戴上它,说话,转录,自动完成
  • 用大白话解释一下“高基数特征”
  • java+webstock
  • 什么是API调用?通俗解释+实际应用场景详解
  • 【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
  • PAN/FPN
  • Flotherm许可的并发用户数限制
  • 【案例解析】一次 TIME_WAIT 导致 TPS 断崖式下降的排查与优化
  • ThreadLocal 源码
  • RabbitMq安装
  • deepseek: GPU 配套
  • 联邦学习同态加密以及常见问题
  • Vue动态/异步组件
  • 1991-2024年上市公司个股换手率数据
  • Haption 力反馈遥操作机器人:6 自由度 + 低延迟响应,解锁精准远程操控体验
  • 设置Outlook关闭时最小化
  • mybatisX的使用,简化springboot的开发,不用再写entity、mapper以及service了!
  • JDK 17 序列化是怎么回事
  • Prompt‏ 工程和优化技巧
  • 产品经理课程(十三)
  • SE(Secure Element)加密芯片与MCU协同工作的典型流程
  • 在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
  • Origin图像数字化工具——如何复制其他人的图表作为对比数据
  • Linux 下部署安装docker
  • 京东商品sku抓取攻略|已封装API接口调用示例
  • SpringBoot配置
  • 【如何做好技术架构】
  • 大模型真的像人一样“思考”和“理解”吗?​
  • Python编程基础(五) | 字典