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

MySQL高级特性详解

MySQL高级特性详解

一、自关联查询

概念

自关联查询是指一个表与它自己进行连接的查询。通常用于处理具有层级关系或递归结构的数据。

应用场景

  • 员工与上级关系
  • 分类的父子关系
  • 地区的层级关系

示例

-- 创建员工表
CREATE TABLE employees (emp_id INT PRIMARY KEY,emp_name VARCHAR(50),manager_id INT,FOREIGN KEY (manager_id) REFERENCES employees(emp_id)
);-- 插入示例数据
INSERT INTO employees VALUES 
(1, '张总', NULL),
(2, '李经理', 1),
(3, '王主管', 2),
(4, '赵员工', 3),
(5, '钱员工', 3);-- 查询每个员工及其直接上级
SELECT e1.emp_name AS '员工',e2.emp_name AS '上级'
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.emp_id;-- 查询所有下属超过1人的管理者
SELECT e2.emp_name AS '管理者',COUNT(e1.emp_id) AS '下属人数'
FROM employees e1
INNER JOIN employees e2 ON e1.manager_id = e2.emp_id
GROUP BY e2.emp_id, e2.emp_name
HAVING COUNT(e1.emp_id) > 1;

二、子查询操作

概念

子查询是嵌套在其他SQL语句中的SELECT语句,可以出现在WHERE、FROM、SELECT等子句中。

子查询分类

1. 标量子查询(返回单个值)
-- 查询工资高于平均工资的员工
SELECT emp_name, salary 
FROM employees 
WHERE salary > (SELECT AVG(salary) FROM employees);
2. 列子查询(返回一列多行)
-- 使用IN操作符
SELECT * FROM employees 
WHERE dept_id IN (SELECT dept_id FROM departments WHERE location = '北京');-- 使用ANY/ALL操作符
SELECT * FROM employees 
WHERE salary > ANY (SELECT salary FROM employees WHERE dept_id = 10);
3. 行子查询(返回一行多列)
-- 查询与张三相同部门和职位的员工
SELECT * FROM employees 
WHERE (dept_id, position) = (SELECT dept_id, position FROM employees WHERE emp_name = '张三'
);
4. 表子查询(返回多行多列)
-- FROM子句中的子查询
SELECT t.dept_name, t.avg_salary
FROM (SELECT d.dept_name, AVG(e.salary) AS avg_salaryFROM employees eJOIN departments d ON e.dept_id = d.dept_idGROUP BY d.dept_name
) t
WHERE t.avg_salary > 10000;

EXISTS子查询

-- 查询有员工的部门
SELECT * FROM departments d
WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.dept_id
);-- 查询没有下属的员工
SELECT * FROM employees e1
WHERE NOT EXISTS (SELECT 1 FROM employees e2 WHERE e2.manager_id = e1.emp_id
);

三、窗口函数

概念

窗口函数在保留原表所有行的基础上,为每一行计算聚合值。与GROUP BY不同,它不会减少返回的行数。

基本语法

函数名() OVER ([PARTITION BY 列名][ORDER BY 列名][窗口子句]
)

常用窗口函数

1. 聚合窗口函数
-- 计算累计销售额
SELECT order_date,amount,SUM(amount) OVER (ORDER BY order_date) AS cumulative_sum,AVG(amount) OVER (ORDER BY order_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM orders;-- 按部门计算工资占比
SELECT emp_name,dept_id,salary,salary / SUM(salary) OVER (PARTITION BY dept_id) * 100 AS salary_percentage
FROM employees;
2. 排名函数
-- ROW_NUMBER(): 生成唯一序号
-- RANK(): 相同值同排名,下一个排名会跳过
-- DENSE_RANK(): 相同值同排名,下一个排名连续SELECT emp_name,dept_id,salary,ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS row_num,RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rank_num,DENSE_RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dense_rank_num
FROM employees;-- NTILE(): 将数据分成N组
SELECT emp_name,salary,NTILE(4) OVER (ORDER BY salary) AS quartile
FROM employees;
3. 偏移函数
-- LAG/LEAD: 访问前后行数据
SELECT month,sales,LAG(sales, 1) OVER (ORDER BY month) AS prev_month_sales,LEAD(sales, 1) OVER (ORDER BY month) AS next_month_sales,sales - LAG(sales, 1) OVER (ORDER BY month) AS month_over_month_change
FROM monthly_sales;-- FIRST_VALUE/LAST_VALUE: 获取窗口内第一个/最后一个值
SELECT emp_name,dept_id,salary,FIRST_VALUE(emp_name) OVER (PARTITION BY dept_id ORDER BY salary DESC) AS highest_paid,LAST_VALUE(emp_name) OVER (PARTITION BY dept_id ORDER BY salary DESCRANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS lowest_paid
FROM employees;

四、MySQL常用内置函数

1. 时间日期函数

-- 获取当前时间
SELECT NOW(), CURDATE(), CURTIME();-- 日期格式化
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日 %H:%i:%s');-- 日期计算
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY) AS '7天后',DATE_SUB(NOW(), INTERVAL 1 MONTH) AS '1个月前',DATEDIFF('2024-12-31', NOW()) AS '距离年底天数',TIMESTAMPDIFF(YEAR, '1990-01-01', NOW()) AS '年龄';-- 提取日期部分
SELECT YEAR(NOW()) AS '年',MONTH(NOW()) AS '月',DAY(NOW()) AS '日',DAYNAME(NOW()) AS '星期',WEEKDAY(NOW()) AS '星期索引';

2. 字符串函数

-- 字符串连接
SELECT CONCAT('Hello', ' ', 'World');
SELECT CONCAT_WS(',', 'A', 'B', 'C'); -- 使用分隔符-- 字符串长度和位置
SELECT LENGTH('你好'), CHAR_LENGTH('你好'); -- 字节长度vs字符长度
SELECT LOCATE('world', 'hello world'); -- 查找位置-- 字符串截取
SELECT LEFT('abcdefg', 3) AS '左截取',RIGHT('abcdefg', 3) AS '右截取',SUBSTRING('abcdefg', 2, 3) AS '中间截取';-- 字符串转换
SELECT UPPER('hello') AS '大写',LOWER('HELLO') AS '小写',REPLACE('hello world', 'world', 'MySQL') AS '替换',TRIM('  hello  ') AS '去空格',REVERSE('hello') AS '反转';

3. 数学函数

-- 基础数学运算
SELECT ABS(-10) AS '绝对值',CEIL(4.3) AS '向上取整',FLOOR(4.7) AS '向下取整',ROUND(4.567, 2) AS '四舍五入',TRUNCATE(4.567, 2) AS '截断';-- 高级数学函数
SELECT POW(2, 3) AS '幂运算',SQRT(16) AS '平方根',MOD(10, 3) AS '取余',RAND() AS '随机数',FLOOR(RAND() * 100) AS '0-99随机整数';

五、CASE WHEN条件判断

简单CASE语法

SELECT emp_name,salary,CASE dept_idWHEN 1 THEN '技术部'WHEN 2 THEN '销售部'WHEN 3 THEN '人事部'ELSE '其他部门'END AS dept_name
FROM employees;

搜索CASE语法

-- 工资等级划分
SELECT emp_name,salary,CASE WHEN salary >= 20000 THEN '高级'WHEN salary >= 10000 THEN '中级'WHEN salary >= 5000 THEN '初级'ELSE '实习'END AS salary_level
FROM employees;-- 条件统计
SELECT dept_id,COUNT(CASE WHEN salary >= 10000 THEN 1 END) AS high_salary_count,COUNT(CASE WHEN salary < 10000 THEN 1 END) AS low_salary_count,SUM(CASE WHEN gender = '男' THEN salary ELSE 0 END) AS male_total_salary,SUM(CASE WHEN gender = '女' THEN salary ELSE 0 END) AS female_total_salary
FROM employees
GROUP BY dept_id;-- 动态排序
SELECT * FROM employees
ORDER BY CASE WHEN @sort_type = 'name' THEN emp_name END,CASE WHEN @sort_type = 'salary' THEN salary END DESC;

六、事务概念及应用

事务的概念

事务是一组不可分割的操作单元,要么全部成功,要么全部失败。

ACID特性

  • 原子性(Atomicity):事务是不可分割的最小操作单元
  • 一致性(Consistency):事务完成后,数据必须处于一致状态
  • 隔离性(Isolation):多个事务之间相互独立
  • 持久性(Durability):事务一旦提交,改变是永久的

事务操作

-- 开启事务
START TRANSACTION; -- 或 BEGIN;-- 执行SQL操作
UPDATE accounts SET balance = balance - 1000 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE account_id = 2;-- 提交或回滚
COMMIT; -- 提交事务
ROLLBACK; -- 回滚事务-- 设置保存点
SAVEPOINT point1;
-- 回滚到保存点
ROLLBACK TO point1;

事务隔离级别

-- 查看当前隔离级别
SELECT @@transaction_isolation;-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; -- 读未提交
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;   -- 读已提交
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;  -- 可重复读(MySQL默认)
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;      -- 串行化

应用场景示例

-- 转账操作
DELIMITER $$
CREATE PROCEDURE transfer_money(IN from_account INT,IN to_account INT,IN amount DECIMAL(10,2)
)
BEGINDECLARE EXIT HANDLER FOR SQLEXCEPTIONBEGINROLLBACK;SELECT 'Transaction failed, rolled back' AS message;END;START TRANSACTION;UPDATE accounts SET balance = balance - amount WHERE account_id = from_account AND balance >= amount;IF ROW_COUNT() = 0 THENSIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Insufficient balance';END IF;UPDATE accounts SET balance = balance + amount WHERE account_id = to_account;COMMIT;SELECT 'Transaction successful' AS message;
END$$
DELIMITER ;

七、索引概念及应用

索引的概念

索引是帮助MySQL高效获取数据的数据结构,类似于书的目录。

索引类型

  1. 主键索引(PRIMARY KEY):唯一且不为NULL
  2. 唯一索引(UNIQUE):唯一,可以为NULL
  3. 普通索引(INDEX):最基本的索引
  4. 全文索引(FULLTEXT):用于全文搜索
  5. 组合索引:多列组成的索引

索引操作

-- 创建索引
CREATE INDEX idx_emp_name ON employees(emp_name);
CREATE UNIQUE INDEX idx_emp_email ON employees(email);
CREATE INDEX idx_emp_dept_salary ON employees(dept_id, salary); -- 组合索引-- 查看索引
SHOW INDEX FROM employees;-- 删除索引
DROP INDEX idx_emp_name ON employees;-- 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM employees WHERE emp_name = '张三';

索引使用原则

-- 1. 最左前缀原则(组合索引)
-- 假设有索引 (a, b, c)
SELECT * FROM table WHERE a = 1; -- 使用索引
SELECT * FROM table WHERE a = 1 AND b = 2; -- 使用索引
SELECT * FROM table WHERE b = 2; -- 不使用索引-- 2. 避免索引失效的情况
-- 函数操作
SELECT * FROM employees WHERE YEAR(hire_date) = 2024; -- 索引失效
SELECT * FROM employees WHERE hire_date >= '2024-01-01' AND hire_date < '2025-01-01'; -- 使用索引-- 类型不匹配
SELECT * FROM employees WHERE emp_id = '123'; -- 如果emp_id是整数,可能失效-- LIKE通配符
SELECT * FROM employees WHERE emp_name LIKE '%张%'; -- 索引失效
SELECT * FROM employees WHERE emp_name LIKE '张%'; -- 使用索引

索引优化建议

  • 选择性高的列适合建索引
  • 频繁作为查询条件的列建索引
  • 经常需要排序的列建索引
  • 避免过多索引,影响写入性能
  • 定期分析和优化索引

八、视图概念及应用

视图的概念

视图是一个虚拟表,其内容由查询定义。视图不存储数据,只存储SQL查询语句。

视图的优点

  1. 简化复杂查询
  2. 数据安全性(隐藏敏感列)
  3. 逻辑数据独立性

视图操作

-- 创建视图
CREATE VIEW v_emp_dept AS
SELECT e.emp_id,e.emp_name,e.salary,d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id;-- 使用视图
SELECT * FROM v_emp_dept WHERE salary > 10000;-- 创建可更新视图
CREATE VIEW v_emp_simple AS
SELECT emp_id, emp_name, salary
FROM employees
WHERE dept_id = 1
WITH CHECK OPTION; -- 确保通过视图的修改符合WHERE条件-- 修改视图
ALTER VIEW v_emp_dept AS
SELECT e.emp_id,e.emp_name,e.salary,e.hire_date,d.dept_name
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id;-- 删除视图
DROP VIEW IF EXISTS v_emp_dept;

视图应用场景

-- 1. 权限控制:为不同用户创建不同视图
CREATE VIEW v_emp_public AS
SELECT emp_id, emp_name, dept_id
FROM employees; -- 隐藏工资信息-- 2. 简化复杂查询
CREATE VIEW v_sales_summary AS
SELECT DATE_FORMAT(order_date, '%Y-%m') AS month,SUM(amount) AS total_sales,COUNT(DISTINCT customer_id) AS customer_count,AVG(amount) AS avg_order_value
FROM orders
GROUP BY DATE_FORMAT(order_date, '%Y-%m');-- 3. 计算字段
CREATE VIEW v_emp_annual AS
SELECT emp_id,emp_name,salary,salary * 12 AS annual_salary,salary * 0.1 AS bonus
FROM employees;

九、ER模型和3NF三范式

ER模型(实体-关系模型)

基本概念
  • 实体(Entity):现实世界中的对象,如学生、课程
  • 属性(Attribute):实体的特征,如学生的姓名、年龄
  • 关系(Relationship):实体之间的联系
关系类型
  1. 一对一(1:1):一个实体对应另一个实体的一个实例
  2. 一对多(1:N):一个实体对应另一个实体的多个实例
  3. 多对多(M:N):多个实体对应另一个实体的多个实例
ER图示例
-- 学生与课程的多对多关系
-- 学生表
CREATE TABLE students (student_id INT PRIMARY KEY,student_name VARCHAR(50),age INT
);-- 课程表
CREATE TABLE courses (course_id INT PRIMARY KEY,course_name VARCHAR(100),credits INT
);-- 选课表(关系表)
CREATE TABLE enrollments (student_id INT,course_id INT,grade DECIMAL(3,1),PRIMARY KEY (student_id, course_id),FOREIGN KEY (student_id) REFERENCES students(student_id),FOREIGN KEY (course_id) REFERENCES courses(course_id)
);

三范式(3NF)

第一范式(1NF):原子性

每个字段都是不可分割的原子值。

-- 违反1NF的设计
CREATE TABLE bad_students (student_id INT,student_name VARCHAR(50),phone_numbers VARCHAR(200) -- 存储多个电话号码,如"13812345678,13987654321"
);-- 符合1NF的设计
CREATE TABLE students (student_id INT PRIMARY KEY,student_name VARCHAR(50)
);CREATE TABLE student_phones (student_id INT,phone_number VARCHAR(20),phone_type VARCHAR(20),PRIMARY KEY (student_id, phone_number),FOREIGN KEY (student_id) REFERENCES students(student_id)
);
第二范式(2NF):完全依赖主键

非主键字段必须完全依赖于主键,不能只依赖主键的一部分。

-- 违反2NF的设计
CREATE TABLE bad_order_items (order_id INT,product_id INT,quantity INT,product_name VARCHAR(100), -- 只依赖于product_id,不依赖于order_idproduct_price DECIMAL(10,2), -- 只依赖于product_idPRIMARY KEY (order_id, product_id)
);-- 符合2NF的设计
CREATE TABLE products (product_id INT PRIMARY KEY,product_name VARCHAR(100),product_price DECIMAL(10,2)
);CREATE TABLE order_items (order_id INT,product_id INT,quantity INT,PRIMARY KEY (order_id, product_id),FOREIGN KEY (product_id) REFERENCES products(product_id)
);
第三范式(3NF):消除传递依赖

非主键字段之间不能有依赖关系,都应该直接依赖于主键。

-- 违反3NF的设计
CREATE TABLE bad_employees (emp_id INT PRIMARY KEY,emp_name VARCHAR(50),dept_id INT,dept_name VARCHAR(50), -- 传递依赖:dept_name依赖于dept_id,而非直接依赖于emp_iddept_location VARCHAR(100) -- 传递依赖
);-- 符合3NF的设计
CREATE TABLE departments (dept_id INT PRIMARY KEY,dept_name VARCHAR(50),dept_location VARCHAR(100)
);CREATE TABLE employees (emp_id INT PRIMARY KEY,emp_name VARCHAR(50),dept_id INT,FOREIGN KEY (dept_id) REFERENCES departments(dept_id)
);

范式化的优缺点

优点
  • 减少数据冗余
  • 保证数据一致性
  • 节省存储空间
  • 更新异常少
缺点
  • 查询时需要更多JOIN操作
  • 可能影响查询性能
反范式化场景

在某些情况下,为了提高查询性能,可能会适度违反范式:

-- 适度冗余以提高查询性能
CREATE TABLE order_summary (order_id INT PRIMARY KEY,order_date DATE,customer_name VARCHAR(100), -- 冗余字段,避免每次都JOINtotal_amount DECIMAL(10,2), -- 计算字段,避免每次都SUMitem_count INT -- 统计字段
);

实战练习题

综合练习:电商数据分析

-- 创建示例表
CREATE TABLE orders (order_id INT PRIMARY KEY,customer_id INT,order_date DATE,total_amount DECIMAL(10,2)
);-- 1. 使用窗口函数计算客户的购买排名
SELECT customer_id,SUM(total_amount) AS total_purchase,RANK() OVER (ORDER BY SUM(total_amount) DESC) AS customer_rank
FROM orders
GROUP BY customer_id;-- 2. 使用子查询找出消费超过平均值的客户
SELECT DISTINCT customer_id
FROM orders o1
WHERE (SELECT SUM(total_amount) FROM orders o2 WHERE o2.customer_id = o1.customer_id
) > (SELECT AVG(customer_total) FROM (SELECT SUM(total_amount) AS customer_total FROM orders GROUP BY customer_id) t
);-- 3. 使用CASE WHEN进行客户分类
SELECT customer_id,SUM(total_amount) AS total_amount,CASE WHEN SUM(total_amount) >= 10000 THEN 'VIP客户'WHEN SUM(total_amount) >= 5000 THEN '重要客户'WHEN SUM(total_amount) >= 1000 THEN '普通客户'ELSE '潜在客户'END AS customer_level
FROM orders
GROUP BY customer_id;

总结

掌握这些MySQL高级特性对于数据库开发和优化至关重要:

  1. 自关联查询子查询提供了灵活的数据查询方式
  2. 窗口函数让复杂的分析查询变得简单高效
  3. 内置函数CASE WHEN增强了SQL的表达能力
  4. 事务确保了数据的完整性和一致性
  5. 索引是提升查询性能的关键
  6. 视图简化了复杂查询并提供了安全性
  7. ER模型范式化是良好数据库设计的基础

建议通过大量实践来深入理解这些概念,并在实际项目中灵活运用。


文章转载自:

http://OIQnA2k9.hxxwq.cn
http://VUoCJ455.hxxwq.cn
http://lb2WJiHU.hxxwq.cn
http://OxTGcxZU.hxxwq.cn
http://cMtiPvhx.hxxwq.cn
http://J31Lsbuy.hxxwq.cn
http://wusMBc0d.hxxwq.cn
http://y5q9mzMB.hxxwq.cn
http://2PkfDTcq.hxxwq.cn
http://es9Olbg6.hxxwq.cn
http://26QIdjYf.hxxwq.cn
http://fjM3tZUb.hxxwq.cn
http://gXVlURe4.hxxwq.cn
http://N4lW78xc.hxxwq.cn
http://ODsgo1fN.hxxwq.cn
http://lZJovZ5i.hxxwq.cn
http://ioWbif4V.hxxwq.cn
http://16OM1RVz.hxxwq.cn
http://9Qr8Wf3F.hxxwq.cn
http://EGo6aFaR.hxxwq.cn
http://D1qH1zgW.hxxwq.cn
http://A5rvVX94.hxxwq.cn
http://T0TQjCJO.hxxwq.cn
http://0dXnbsEq.hxxwq.cn
http://lVvJoaR8.hxxwq.cn
http://JU8rH34l.hxxwq.cn
http://FWqClGqZ.hxxwq.cn
http://PxRzteZr.hxxwq.cn
http://YU8GAe2D.hxxwq.cn
http://ZNh6aOHl.hxxwq.cn
http://www.dtcms.com/a/373012.html

相关文章:

  • 【Claude Code】 保姆级教程
  • 【Pywinauto库】0. Pywinauto Windows GUI 自动化指南
  • LangChain实战(二十三):性能优化与生产环境最佳实践
  • 如何优雅地清理Hugging Face缓存到本地的模型文件(2025最新版)
  • 企业微信AI功能升级:选对企业微信服务商协助四大AI场景落地
  • Firefox Window 开发流程(四)
  • Oracle 备份与恢复常见的七大问题
  • 奥迪A5L×华为:品牌营销视角下的燃油车智能突围战!
  • LAMPSecurity: CTF5靶场渗透
  • 【Java实战㉟】Spring Boot与MyBatis:数据库交互的进阶之旅
  • 金融量化指标--3Beta 贝塔
  • leetcode10(跳跃游戏 II)
  • <数据集>无人机航拍人员搜救识别数据集<目标检测>
  • [每周一更]-(第159期):Go 工程师视角:容器化技术(Docker/Kubernetes)与CI/CD流程的应用场景
  • 低代码拖拽实现与bpmn-js详解
  • 六、Docker 核心技术:Dockerfile 指令详解
  • scp 网间拷贝
  • 20250908_开启10.1.3.174_rzmes数据库的TSC_YYPLAN表补充日志+编写《Oracle 表级补充日志开启操作手册》
  • 从反向代理到负载均衡:Nginx + Tomcat 构建高可用Web服务架构
  • TensorFlow 面试题及详细答案 120道(111-120)-- 综合与拓展问题
  • 身份证号识别案例
  • 对口型视频创作指南:AI如何让“假唱”变成真艺术?
  • [免费]基于Python的协同过滤电影推荐系统(Django+Vue+sqlite+爬虫)【论文+源码+SQL脚本】
  • Spark RDD转DataFrame的三种方式
  • Gradio全解10——Streaming:流式传输的音频应用(7)——ElevenLabs:高级智能语音技术
  • 通义万相wan2.2 Fun系列--Camera镜头控制与lnp首尾帧视频模型
  • AI Coding — 基于RAG的Token窗口优化方案
  • Mac OS上搭建 http server
  • springboot项目详细配置rabbitmq及使用rabbitmq完成评论功能
  • ios面试八股文