【SQL必知必会】SELECT语句各关键字的执行顺序详解 - 程序员面试高频考点

#代码星辉·七月创作之星挑战赛#

作者:唐叔在学习
专栏:数据库学习
SEO关键词:SQL执行顺序、SELECT语句、SQL优化、大数据开发、数据分析、LeetCode SQL、MySQL、SQL面试题、GROUP BY、HAVING、JOIN、WHERE、ORDER BY、LIMIT、分页查询、SQL调优

大家好,我是你们的老朋友唐叔!今天我们来聊聊SQL中最核心的SELECT语句的执行顺序问题。这个问题在程序员面试中出现的频率极高,也是很多新手容易搞混的知识点。掌握它不仅能让你的SQL查询更高效,还能在面试中脱颖而出!

一、为什么需要了解SELECT执行顺序?

很多同学写SQL时,只是机械地按照SELECT-FROM-WHERE这样的顺序写,却不了解数据库引擎实际执行的顺序。这就好比你知道汽车的油门、刹车和方向盘在哪,但不知道它们的工作原理,遇到复杂路况就容易出问题。

面试高频考点:90%的SQL面试都会问到执行顺序问题,特别是大数据开发、数据分析师等岗位。

二、SELECT语句的"表面顺序"和"真实顺序"

1. 我们写的顺序(表面顺序)

SELECT [DISTINCT] 列名
FROM 表名
[JOIN 表名 ON 连接条件]
[WHERE 条件]
[GROUP BY 分组列]
[HAVING 分组后条件]
[ORDER BY 排序列]
[LIMIT 行数]

2. 数据库执行的顺序(真实顺序)

这才是重点!数据库引擎实际是这样处理的:

  1. FROM:先确定数据来源(查哪张表)
  2. JOIN:如果有表连接,此时执行
  3. WHERE:对原始数据进行过滤
  4. GROUP BY:对过滤后的数据分组
  5. HAVING:对分组后的结果再过滤
  6. SELECT:选择要显示的列
  7. DISTINCT:去重
  8. ORDER BY:排序
  9. LIMIT:限制返回行数

唐叔口诀:弗(FROM)建(JOIN)委(WHERE)组(GROUP BY)会(HAVING)选(SELECT)帝(DISTINCT)欧(ORDER BY)李(LIMIT)

三、各关键字详解与避坑指南

1. FROM - 数据来源

语法FROM table1 [AS alias1]

注意事项

  • 多表查询时,小表放前面性能更好(SQL优化技巧)
  • 表别名可以提高可读性

2. JOIN - 表连接(大数据开发重点)

类型

  • INNER JOIN(内连接)
  • LEFT JOIN(左连接)
  • RIGHT JOIN(右连接)
  • FULL JOIN(全连接)
  • CROSS JOIN(笛卡尔积)

避坑

-- 错误写法(ON条件放WHERE后面)
SELECT * FROM A JOIN B WHERE A.id=B.id

-- 正确写法
SELECT * FROM A JOIN B ON A.id=B.id

3. WHERE - 行级过滤

常见错误:在WHERE中使用SELECT中定义的别名(此时别名还不存在!)

-- 错误示例
SELECT salary*12 AS annual_salary 
FROM employees 
WHERE annual_salary > 100000  -- 报错!

-- 正确写法
SELECT salary*12 AS annual_salary 
FROM employees 
WHERE salary*12 > 100000

在这里插入图片描述

4. GROUP BY - 分组统计(数据分析核心)

语法GROUP BY column1 [, column2...]

黄金法则:SELECT中的非聚合列必须出现在GROUP BY中

-- 错误示例
SELECT Name, Description, COUNT(Name) 
FROM Product 
GROUP BY Name -- Description不在GROUP BY中

-- 正确写法
SELECT Name, Description, COUNT(Name) 
FROM Product 
GROUP BY Name, Description

在这里插入图片描述
常见的聚合列有:

函数说明示例
COUNT()计数COUNT(*) 计算行数
SUM()求和SUM(salary) 计算总和
AVG()平均值AVG(score) 计算平均分
MAX()最大值MAX(price) 找出最贵价格
MIN()最小值MIN(age) 找出最小年龄

5. HAVING - 分组后过滤

与WHERE的区别:

  • WHERE过滤原始数据
  • HAVING过滤分组后的数据
-- 查询平均工资>50000的部门
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000

6. SELECT - 选择列

性能提示

  • 避免使用SELECT *,只查询需要的列
  • 计算列会消耗性能

7. ORDER BY - 排序

语法ORDER BY column1 [ASC|DESC] [, column2...]

注意

  • 排序是性能杀手,大数据量时要谨慎
  • 可以按SELECT中的别名排序

8. LIMIT - 限制行数(分页查询必备)

分页公式LIMIT (page_num-1)*page_size, page_size

四、实战案例分析(LeetCode高频题型)

案例1:查询各部门薪资最高的员工

原题:https://leetcode.cn/problems/department-highest-salary/description/

SELECT e.department, e.employee_name, e.salary
FROM employees e
WHERE (e.department, e.salary) IN (
    SELECT department, MAX(salary)
    FROM employees
    GROUP BY department
)
ORDER BY e.salary DESC;

执行顺序分析

  1. 先执行子查询中的FROM-GROUP BY-SELECT
  2. 然后执行主查询的FROM-WHERE-SELECT-ORDER BY

案例2:LeetCode第176题 - 第二高的薪水

原题:https://leetcode.cn/problems/second-highest-salary/description/

SELECT (
    SELECT DISTINCT salary
    FROM employee
    ORDER BY salary DESC
    LIMIT 1 OFFSET 1
) AS SecondHighestSalary;

五、性能优化建议(SQL调优关键)

  1. WHERE条件中避免使用函数,会导致索引失效

    -- 不好
    WHERE YEAR(create_time) = 2023
    
    -- 好
    WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
    
  2. 多表JOIN时,小表驱动大表

  3. GROUP BY字段加上索引

六、常见面试题

  1. WHERE和HAVING的区别是什么?
  2. GROUP BY和ORDER BY可以一起用吗?
  3. LIMIT可以在子查询中使用吗?
  4. 如何优化一个执行很慢的SELECT查询?

(答案都在文中哦~)

总结

记住唐叔的口诀:弗建委会选帝欧李(FROM-JOIN-WHERE-GROUP BY-HAVING-SELECT-DISTINCT-ORDER BY-LIMIT),SELECT语句的执行顺序就再也不会搞混了!

觉得有用的话,别忘了点赞收藏!


往期数据库文章推荐

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值