my sql 常用函数及语句的执行顺序

MySQL 常用函数

1. 字符串函数

sql 复制代码
-- 连接
SELECT CONCAT('Hello', ' ', 'World'); -- Hello World
SELECT CONCAT_WS(',', 'John', 'Doe'); -- John,Doe

-- 截取和长度
SELECT SUBSTRING('MySQL', 3, 3); -- SQL
SELECT LEFT('MySQL', 2); -- My
SELECT RIGHT('MySQL', 3); -- SQL
SELECT LENGTH('MySQL'); -- 5
SELECT CHAR_LENGTH('MySQL'); -- 5

-- 大小写转换
SELECT UPPER('mysql'); -- MYSQL
SELECT LOWER('MYSQL'); -- mysql

-- 去除空格
SELECT TRIM('  MySQL  '); -- MySQL
SELECT LTRIM('  MySQL'); -- MySQL
SELECT RTRIM('MySQL  '); -- MySQL

-- 替换和查找
SELECT REPLACE('Hello World', 'World', 'MySQL'); -- Hello MySQL
SELECT REPLACE('abc abc', 'abc', 'x'); -- x x
SELECT INSTR('MySQL', 'SQL'); -- 3
SELECT LOCATE('SQL', 'MySQL SQL'); -- 3
SELECT POSITION('SQL' IN 'MySQL'); -- 3

2. 数值函数

sql 复制代码
-- 基本数学函数
SELECT ABS(-10); -- 10
SELECT ROUND(3.14159, 2); -- 3.14
SELECT CEIL(3.14); -- 4
SELECT FLOOR(3.14); -- 3
SELECT TRUNCATE(3.14159, 2); -- 3.14

-- 随机数和符号
SELECT RAND(); -- 0-1之间的随机数
SELECT SIGN(-10); -- -1
SELECT SIGN(10); -- 1
SELECT SIGN(0); -- 0

-- 幂和平方根
SELECT POWER(2, 3); -- 8
SELECT SQRT(16); -- 4
SELECT EXP(1); -- 2.718
SELECT LN(10); -- 2.302
SELECT LOG(10, 100); -- 2

3. 日期时间函数

sql 复制代码
-- 当前时间
SELECT NOW(); -- 2024-01-15 10:30:25
SELECT CURDATE(); -- 2024-01-15
SELECT CURTIME(); -- 10:30:25
SELECT UNIX_TIMESTAMP(); -- 时间戳

-- 日期提取
SELECT YEAR('2024-01-15'); -- 2024
SELECT MONTH('2024-01-15'); -- 1
SELECT DAY('2024-01-15'); -- 15
SELECT HOUR('10:30:25'); -- 10
SELECT MINUTE('10:30:25'); -- 30

-- 日期计算
SELECT DATE_ADD('2024-01-15', INTERVAL 7 DAY); -- 2024-01-22
SELECT DATE_SUB('2024-01-15', INTERVAL 1 MONTH); -- 2023-12-15
SELECT DATEDIFF('2024-01-20', '2024-01-15'); -- 5
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'); -- 2024-01-15 10:30:25

4. 条件函数

sql 复制代码
-- CASE WHEN
SELECT 
    name,
    salary,
    CASE 
        WHEN salary > 10000 THEN '高薪'
        WHEN salary > 5000 THEN '中薪'
        ELSE '低薪'
    END as salary_level
FROM employees;

-- IF函数
SELECT IF(score >= 60, '及格', '不及格') as result FROM students;
SELECT IFNULL(NULL, '默认值'); -- 默认值
SELECT COALESCE(NULL, NULL, '第一个非空值'); -- 第一个非空值

-- 空值处理
SELECT NULLIF(10, 10); -- NULL
SELECT NULLIF(10, 20); -- 10

5. 窗口函数(MySQL 8.0+)

sql 复制代码
-- 排名函数
SELECT 
    name,
    salary,
    ROW_NUMBER() OVER (ORDER BY salary DESC) as rn,
    RANK() OVER (ORDER BY salary DESC) as rk,
    DENSE_RANK() OVER (ORDER BY salary DESC) as dr
FROM employees;

-- 聚合窗口函数
SELECT 
    department,
    name,
    salary,
    AVG(salary) OVER (PARTITION BY department) as avg_dept_salary,
    SUM(salary) OVER (PARTITION BY department) as total_dept_salary
FROM employees;

SQL 语句执行顺序

逻辑执行顺序:

sql 复制代码
-- 书写顺序
SELECT DISTINCT column, aggregate_function
FROM table1
JOIN table2 ON join_condition
WHERE where_condition
GROUP BY group_columns
HAVING having_condition
ORDER BY order_columns
LIMIT limit_count;

-- 实际执行顺序
1. FROM 和 JOIN
2. WHERE
3. GROUP BY
4. HAVING
5. SELECT
6. DISTINCT
7. ORDER BY
8. LIMIT

详细执行步骤:

1. FROM 和 JOIN - 确定数据源
sql 复制代码
FROM employees e
JOIN departments d ON e.dept_id = d.id
  • 执行表连接
  • 生成虚拟表 VT1
2. WHERE - 行级过滤
sql 复制代码
WHERE e.salary > 5000 AND d.name = 'IT'
  • 过滤不符合条件的行
  • 生成虚拟表 VT2
3. GROUP BY - 分组
sql 复制代码
GROUP BY e.department, YEAR(e.hire_date)
  • 按指定列分组
  • 生成虚拟表 VT3
4. HAVING - 组级过滤
sql 复制代码
HAVING AVG(e.salary) > 8000
  • 过滤不符合条件的分组
  • 生成虚拟表 VT4
5. SELECT - 选择列
sql 复制代码
SELECT e.department, 
       YEAR(e.hire_date) as hire_year,
       COUNT(*) as emp_count,
       AVG(e.salary) as avg_salary
  • 计算表达式
  • 生成虚拟表 VT5
6. DISTINCT - 去重
sql 复制代码
SELECT DISTINCT department, hire_year
  • 去除重复行
  • 生成虚拟表 VT6
7. ORDER BY - 排序
sql 复制代码
ORDER BY hire_year DESC, avg_salary ASC
  • 排序结果集
  • 生成虚拟表 VT7
8. LIMIT - 限制行数
sql 复制代码
LIMIT 10
  • 返回指定数量的行

完整示例:

sql 复制代码
-- 查询:找出IT部门平均薪资最高的前3个入职年份
SELECT 
    YEAR(hire_date) as hire_year,
    AVG(salary) as avg_salary,
    COUNT(*) as employee_count
FROM employees e
JOIN departments d ON e.dept_id = d.id
WHERE d.name = 'IT' 
    AND e.salary IS NOT NULL
GROUP BY YEAR(hire_date)
HAVING AVG(salary) > 5000
    AND COUNT(*) >= 5
ORDER BY avg_salary DESC
LIMIT 3;

-- 执行顺序解析:
-- 1. FROM + JOIN: 连接employees和departments表
-- 2. WHERE: 过滤IT部门且薪资不为空的员工
-- 3. GROUP BY: 按入职年份分组
-- 4. HAVING: 过滤平均薪资>5000且员工数>=5的组
-- 5. SELECT: 选择年份、平均薪资、员工数量
-- 6. ORDER BY: 按平均薪资降序排序
-- 7. LIMIT: 返回前3条记录

重要注意事项:

  1. WHERE 中不能使用 SELECT 别名(因为 WHERE 先于 SELECT 执行)
  2. HAVING 中可以使用聚合函数(因为 HAVING 在 GROUP BY 之后执行)
  3. ORDER BY 中可以使用 SELECT 别名(因为 ORDER BY 在 SELECT 之后执行)
  4. 窗口函数在 SELECT 阶段执行,但可以在 ORDER BY 中使用

理解这个执行顺序对于编写高效、正确的 SQL 查询非常重要!

相关推荐
Gold Steps.3 小时前
从 “T+1” 到 “秒级”:MySQL+Flink+Doris 构建实时数据分析全链路
大数据·数据库·数据分析
花北城3 小时前
【MySQL】Oracle与MySQL,跨库数据转储
数据库·mysql·oracle
元Y亨H3 小时前
SQL Join 中函数使用对性能的影响与优化方法
sql
没有bug.的程序员3 小时前
MySQL 配置调优参数:从基础到生产级优化指南
java·数据库·mysql·优化·mysql配置调优
optimistic_chen3 小时前
【Java EE进阶 --- SpringBoot】Mybatis操作数据库(基础)
数据库·经验分享·spring boot·笔记·spring·java-ee·mybatis
支付宝小程序云4 小时前
百宝箱开放平台 ✖️ 查询信息列表
数据库
对着晚风做鬼脸4 小时前
MySQL进阶知识点(六)---- 存储引擎
数据库·mysql
百锦再4 小时前
从 .NET 到 Java 的转型指南:详细学习路线与实践建议
android·java·前端·数据库·学习·.net·数据库架构
卷Java4 小时前
uni-app 模板语法修复说明
java·数据库·spring boot·uni-app·mybatis