DELETE p1FROM Person p1JOIN Person p2 ON p1.email = p2.emailWHERE p1.id > p2.id;
你可以理解为这样两句:
WITH tmp AS ( SELECT p1.id FROM Person p1, Person p2 WHERE p1.email = p2.email AND p1.id > p2.id)DELETEFROM Person p1WHERE p1.id IN ( SELECT id FROM tmp );
先查询出符合条件的项,然后再删除它。
DQL语句
DQL是数据查询语言,用来查询数据库中表的记录。
SELECT 字段列表FROM 表名列表WHERE 条件列表GROUP BY 分组字段列表HAVING 分组后条件列表ORDER BY 排序字段列表LIMIT 分页参数
WITH c AS (SELECT 'Low Salary' AS category UNION ALL SELECT 'Average Salary' UNION ALL SELECT 'High Salary')SELECT category, COUNT(l.level) accounts_countFROM (SELECT *, CASE WHEN income < 20000 THEN 'Low Salary' WHEN (income >= 20000 AND income <= 50000) THEN 'Average Salary' ELSE 'High Salary' END level FROM Accounts) AS l RIGHT JOIN c ON l.level = c.categoryGROUP BY c.category;
CTE递归:
WITH RECURSIVE cte_name AS ( -- ① 锚点查询(Anchor Member):初始数据 SELECT ... FROM ... WHERE ... -- 起点条件 UNION ALL -- ② 递归成员(Recursive Member):引用自己 SELECT ... FROM cte_name JOIN ... WHERE ... -- 递归条件)-- ③ 主查询:使用递归结果SELECT * FROM cte_name;
执行流程 :
先运行锚点查询,得到初始结果集。
把结果集传给递归成员查询,生成下一层数据。
不断重复,直到递归成员不再返回新行。
合并所有层的结果返回。
多个CET
SQL查询可以创建多个CET表
WITH table1 AS (...), table2 AS (...), table3 AS (...)SELECT ...FROM ...;
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';
删除用户
DROP USER '用户名'@'主机名';
权限控制
常用权限:
权限
说明
ALL, ALL PRIVILEGES
所有权限
SELECT
查询数据
INSERT
插入数据
UPDATE
修改数据
DELETE
删除数据
ALTER
修改表
DROP
删除数据库/表/视图
CREATE
创建数据库/表
查询用户权限
SHOW GRANTS FOR '用户名'@'主机名';
授予权限
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';
撤销权限
REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';
多个权限之间,使用 ,分割
授权时,数据库名和表名可以使用*****进行通配,代表所有。
函数
函数是指一段可以直接被另一程段程序调用的程序或代码。
字符串函数
MySQL中内置了很多字符串函数,常用的几个如下:
函数
功能
CONCAT(S1,S2,...Sn)
字符串拼接,将S1,S2,…Sn拼接成一个字符串
LOWER(str)
将字符串str全部转为小写
UPPER(str)
将字符串str全部转为大写
LPAD(str,n,pad)
左填充,用字符串pad对str的左边进行填充,达到n个字符串长度
RPAD(str,n,pad)
右填充,用字符串pad对str的右边进行填充,达到n个字符串长度
TRIM(str)
去掉字符串头部和尾部的空格
SUBSTRING(str,start,len)
返回从字符串str从start位置起的len个长度的字符串
SUBSTRING函数的下标从1开始。
数值函数
常见的数值函数如下:
函数
功能
CEIL(x)
向上取整
FLOOR(x)
向下取整
MOD(x,y)
返回 x % y 的值
RAND()
返回0~1内的随机数
ROUND(x,y)
求参数x的四舍五入的值,保留y位小数
日期函数
常见的日期函数如下:
函数
功能
CURDATE()
返回当前日期
CURTIME()
返回当前时间
NOW()
返回当前日期和时间
YEAR(date)
获取指定date的年份
MONTH(date)
获取指定date的月份
DAY(date)
获取指定date的日期
DATE_ADD(date, INTERVAL expr type)
返回一个日期/时间值加上一个时间间隔expr后的时间值
DATEDIFF(date1,date2)
返回 date1减去 date2之间的天数
DATE_FORMAT(date, format)
按照指定的 format格式化 date值如:%Y-%m
流程函数
流程函数也是很常用的一类函数,可以在SQL语句中实现条件筛选,从而提高语句的效率。
函数
功能
IF(value,t,f)
如果value为true,则返回t;否则返回f
IFNULL(value1,value2)
如果value1不为空,返回value1;否则返回value2
CASE WHEN [val1] THEN [res1] ... ELSE [default] END
如果val为true,返回res1,… 否则返回default默认值
CASE [expr] WHEN [val1] THEN [res1] ... ELSE [default] END
如果expr的值等于val1,返回res1,… 否则返回default默认值
窗口函数
保留原有所有行,每行基于指定“窗口”计算一个值。
函数类别
常用函数
功能说明
常见用途
示例
排序与排名
ROW_NUMBER()
按指定顺序为每行生成唯一序号(不重复)
去重取第一条记录、分页查询
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC)
RANK()
按顺序排名,相同值并列,后续名次会跳过
比赛排名、统计并列名次
RANK() OVER (ORDER BY score DESC)
DENSE_RANK()
与 RANK() 类似,但名次不跳过
班级并列成绩排名
DENSE_RANK() OVER (ORDER BY score DESC)
累计与聚合
SUM()
在窗口内求和
累计销售额、滚动求和
SUM(sales) OVER (PARTITION BY region ORDER BY month)
AVG()
在窗口内取平均值
统计区间均值
AVG(score) OVER (PARTITION BY class)
COUNT()
在窗口内计数
统计分组记录数
COUNT(*) OVER (PARTITION BY dept)
取前后值
LAG()
获取当前行之前第 n 行的值
同环比分析、趋势对比
LAG(sales, 1) OVER (ORDER BY month)
LEAD()
获取当前行之后第 n 行的值
预测下一期数据
LEAD(sales, 1) OVER (ORDER BY month)
边界值
FIRST_VALUE()
获取窗口内排序后的第一行值
获取某分组最早/最低数据
FIRST_VALUE(salary) OVER (PARTITION BY dept ORDER BY salary)
LAST_VALUE()
获取窗口内排序后的最后一行值
获取某分组最新/最高数据
LAST_VALUE(salary) OVER (PARTITION BY dept ORDER BY salary)
偏移计算
NTILE(n)
将结果集划分为 n 份,返回每行所属区间编号
分位数统计
NTILE(4) OVER (ORDER BY salary DESC)
OVER 子句 是窗口函数的关键,可搭配:
PARTITION BY:按组划分窗口
ORDER BY:定义窗口内的排序
ROWS/RANGE:指定窗口的行范围
约束
概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。
目的:保证数据库中数据的正确、有效和完整。
约束
描述
关键字
非空约束
限制该字段的数据不能为null
NOT NULL
唯一约束
保证该字段的所有数据都是唯一、不重复的
UNIQUE
主键约束
主键是一行数据的唯一标识,要求非空且唯一
PRIMARY KEY
默认约束
保存数据时,如果未指定该字段的值,则采用默认值
DEFAULT
检查约束 (8.0.16版本之后)
保证字段值满足指定条件
CHECK
外键约束
用来让两张表的数据之间建立连接,保证数据的一致性和完整性
FOREIGN KEY
约束是作用于表中字段上的,可以在创建表/修改表的时间添加约束。
一个字段可以添加多个约束。
示例:
1755004721798
CREATE TABLE User( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '唯一标识', name VARCHAR(10) NOT NULL UNIQUE COMMENT '姓名', age INT CHECK ( age > 0 AND age <= 120 ) COMMENT '年龄', status char(1) DEFAULT '1' COMMENT '状态', gender char(1) COMMENT '性别');