SQL学习
SQL执行顺序:
第1步:FROM - 找到数据源
FROM users u |
MySQL首先要知道数据从哪里来,所以第一步是确定表和给表起别名。
这一步做了什么?
- 找到指定的表
- 为表创建别名(如果有的话)
- 准备读取数据
第2步:JOIN - 连接多张表
FROM users u |
如果查询涉及多张表,MySQL会根据JOIN条件将它们连接起来。
常见的JOIN类型:
INNER JOIN:只返回两表都有的数据LEFT JOIN:返回左表所有数据,右表没有则为NULLRIGHT JOIN:返回右表所有数据,左表没有则为NULL
-- 示例:查询用户及其订单信息 |
第3步:WHERE - 过滤不需要的行
WHERE u.age > 18 AND u.status = 'active' |
在分组之前,MySQL会根据WHERE条件过滤掉不符合条件的行。
注意:WHERE不能使用聚合函数!
-- ❌ 错误写法 |
第4步:GROUP BY - 数据分组
GROUP BY u.department, u.position |
将数据按照指定的列进行分组,为聚合函数做准备。
分组示例:
-- 按部门统计员工数量 |
第5步:HAVING - 过滤分组
HAVING COUNT(*) > 10 |
HAVING是对分组后的结果进行过滤,可以使用聚合函数。
WHERE vs HAVING 对比:
| 条件 | WHERE | HAVING |
|---|---|---|
| 执行时机 | 分组前 | 分组后 |
| 过滤对象 | 行 | 分组 |
| 能否使用聚合函数 | ❌ | ✅ |
-- 找出订单数量超过10的用户 |
第6步:SELECT - 选择要显示的列
SELECT u.name, u.age, COUNT(o.id) as order_count |
到了这一步,MySQL才开始处理SELECT子句,选择要显示的列。
这就是为什么WHERE不能使用SELECT中定义的别名!
-- ❌ 错误:WHERE执行在SELECT之前 |
第7步:DISTINCT - 去除重复
SELECT DISTINCT department |
如果使用了DISTINCT,MySQL会去除重复的行。
第8步:ORDER BY - 排序
ORDER BY u.age DESC, u.name ASC |
对最终结果进行排序。
ORDER BY可以使用SELECT中的别名:
-- ✅ 正确:ORDER BY执行在SELECT之后 |
第9步:LIMIT - 限制结果数量
LIMIT 10 OFFSET 20 |
最后一步,限制返回的结果数量。
💡 实战案例:执行顺序的应用
让我们通过一个实际案例来理解执行顺序:
-- 需求:查询每个部门中年龄大于25岁的员工数量, |
执行过程分析:
- FROM users - 确定数据源
- WHERE age > 25 - 过滤年龄大于25的员工
- GROUP BY department - 按部门分组
- HAVING COUNT(*) > 5 - 过滤员工数量超过5的部门
- SELECT department, COUNT(*) - 选择要显示的列
- ORDER BY employee_count DESC - 按员工数量降序排列
SQL操作/关键字
SQL操作
JOIN详解
⏺ 1. JOIN 的分类和对比

SELECT DISTINCT
SELECT DISTINCT column1, column2, ...FROM table_name;
distinct后可以接多个列,返回这些列不全重复的值。
UNION
SQL UNION 操作符用于组合两个或多个 SELECT 语句的结果集。
- 在
UNION中的每个SELECT语句都必须具有相同数量的列。 - 列也必须具有相似的数据类型。
- 每个
SELECT语句中的列也必须以相同的顺序排列。
UNION 语法
SELECT column_name(s) FROM table1
并集
SELECT column_name(s) FROM table2;
UNION ALL 语法
默认情况下,UNION 操作符只选择不重复的值。要允许重复值,请使用 UNION ALL。
ROUND() 函数
ROUND() 函数用于把数值字段舍入为指定的小数位数。
SQL ROUND() 语法
**SELECT** ROUND(column_name,decimals) **FROM** **TABLE_NAME**;
CASE WHEN THEN
CASE 表达式会逐一检查条件,并在第一个条件满足时返回值(类似于 if-then-else 语句)。因此,一旦某个条件为真,它就会停止读取并返回结果。如果没有条件为真,它将返回 ELSE 子句中的值。如果没有 ELSE 部分且没有任何条件为真,则返回 NULL。
CASE 的本质
CASE 是一个条件表达式,它在每一行数据上进行计算,根据条件返回不同的值。
执行流程
SELECT |
底层执行:
- 扫描表 - 逐行读取 user_profile 的所有行
- 计算 CASE - 对每一行执行 CASE 逻辑:
行1: age=20 → CASE判断 → ‘25岁以下’
行2: age=30 → CASE判断 → ‘25岁及以上’
行3: age=NULL → CASE判断 → ‘25岁以下’
行4: age=26 → CASE判断 → ‘25岁及以上’
…
- 创建临时结果集 - 产生一个临时列:
age | CASE结果
-——–
20 | ‘25岁以下’
30 | ‘25岁及以上’
NULL| ‘25岁以下’
26 | ‘25岁及以上’
- GROUP BY - 按这个临时列的值分组
- 聚合 - 计算 COUNT(*)
CASE 语法
CASE |
窗口函数
https://www.zhihu.com/tardis/zm/art/92654574?source_id=1005
窗口函数的基本语法如下:
<窗口函数> over (partition by <用于分组的列名> |
那么语法中的<窗口函数>都有哪些呢?
<窗口函数>的位置,可以放以下两种函数:
1) 专用窗口函数,包括后面要讲到的rank, dense_rank, row_number等专用窗口函数。
2) 聚合函数,如sum. avg, count, max, min等
因为窗口函数是对where或者group by子句处理后的结果进行操作,所以窗口函数原则上只能写在select子句中。
IF函数
IF() 函数在条件为 TRUE 时返回一个值,在条件为 FALSE 时返回另一个值。
语法
IF(condition, value_if_true, value_if_false)
字符串操作
SUBSTRING_INDEX
SUBSTRING_INDEX() 函数在指定分隔符出现次数之前返回字符串的子串。
语法
SUBSTRING_INDEX(string, delimiter, number)
CONCAT/CONCAT_WS
把字符串连接起来。
语法:CONCAT_AS(separator,str1,str2,...)
separator是必要的分隔符,concat中不需要。
FIND_IN_SET
找到字符在一个字符串中的索引位置。
RegExp正则表达式
正则表达式用来匹配文本的特殊的串(字符集合)(匹配文本,将一个模式(正则表达式)与一个文本串进行比较)。
和LIKE相似,但是有不一样的空白元字符:
| 模式 | 描述 |
|---|---|
| ? | 问号可用于与字符匹配 0 次或 1 次。例如,'colou?r' 匹配 color 和 colour。 |
| $/% | 匹配输入字符串的结束/开始位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前/后的位置。 |
| . | 匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用像 ‘[.\n]’ 的模式。 |
| […] | 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。 |
| [^…] | 负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’。 |
| p1|p2|p3 | 匹配 p1 或 p2 或 p3。例如,’z|food’ 能匹配 “z” 或 “food”。’(z|f)ood’ 则匹配 “zood” 或 “food”。 |
| * | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等价于{0,}。 |
| + | 匹配前面的子表达式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 |
| {n} | n 是一个非负整数。匹配确定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 |
| {n,m} | m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。 |
eg.phone_number REGEXP "^[0-9]{3}-?[0-9]{3}-?[0-9]{4}$"该表达式反映了
LIKE
一般配合WHERE使用,可在列中搜索指定的模式。
ep:`* WHERE something LIKE “%1_”*…
一般LIKE和会和通配符一起使用,
通配符字符
| 符号 | 描述 |
|---|---|
| % | 表示零个或多个字符 |
| _ | 表示单个字符 |
| [] | 表示括号内的任何单个字符 * |
| ^ | 表示括号内不在的任何字符 * |
| - | 表示指定范围内的任何单个字符 * |
| {} | 表示任何转义字符 ** |
数值函数
数值处理
| 函数 | 说明 |
|---|---|
| SIN() | 正弦 |
| COS() | 余弦 |
| TAN() | 正切 |
| ABS() | 绝对值 |
| SQRT() | 平方根 |
| MOD() | 余数 |
| EXP() | 指数 |
| PI() | 圆周率 |
| RAND() | 随机数 |
| CELL()/FLOOR() | 向上取整/向下取整 |