SQL 常用函数大全:聚合、字符串、数值、日期、窗口函数解析

SQL 常用函数大全:聚合、字符串、数值、日期、窗口函数解析

一、聚合函数(用于统计分析)

聚合函数用于对一组值进行计算并返回单个值,常与 GROUP BY 配合使用。

函数 作用 示例
COUNT() 统计行数 SELECT COUNT(*) AS 总记录数 FROM students;(统计学生表总人数)SELECT COUNT(DISTINCT class) AS 班级数 FROM students;(统计不重复的班级数)
SUM() 求和 SELECT SUM(score) AS 总分 FROM exam WHERE student_id = 1001;(计算 1001 号学生的总分)
AVG() 求平均值 SELECT AVG(score) AS 平均分 FROM exam WHERE class = '高一(1)班';(计算高一 1 班平均分)
MAX() 求最大值 SELECT MAX(score) AS 最高分 FROM exam;(查询所有考试成绩的最高分)
MIN() 求最小值 SELECT MIN(age) AS 最小年龄 FROM students;(查询学生表中最小年龄)

二、字符串函数(处理文本数据)

不同数据库(MySQL/PostgreSQL/SQL Server)的字符串函数略有差异,以下以MySQL为例:

函数 作用 示例
CONCAT() 拼接字符串 SELECT CONCAT('姓名:', name, ',年龄:', age) AS 学生信息 FROM students WHERE id = 1;(输出:姓名:张三,年龄:18)
LENGTH() 计算字符串长度(字节) SELECT LENGTH(name) AS 姓名长度 FROM students WHERE id = 1;(张三返回 6,utf8 下一个汉字占 3 字节)
CHAR_LENGTH() 计算字符串长度(字符数) SELECT CHAR_LENGTH(name) AS 姓名字符数 FROM students WHERE id = 1;(张三返回 2)
SUBSTRING() 截取字符串 SELECT SUBSTRING('Hello World', 1, 5) AS 截取结果;(返回 Hello,参数:字符串、起始位置、长度)
UPPER()/LOWER() 转大写 / 小写 SELECT UPPER(name) AS 大写姓名, LOWER(email) AS 小写邮箱 FROM students;
TRIM() 去除首尾空格 SELECT TRIM(' 张三 ') AS 去空格结果;(返回张三)

三、数值函数(处理数字)

以 MySQL 为例:

函数 作用 示例
ROUND() 四舍五入 SELECT ROUND(3.14159, 2) AS 结果;(返回 3.14,第二个参数是保留小数位数)
CEIL() 向上取整 SELECT CEIL(3.1) AS 结果;(返回 4)
FLOOR() 向下取整 SELECT FLOOR(3.9) AS 结果;(返回 3)
ABS() 绝对值 SELECT ABS(-5) AS 结果;(返回 5)
MOD() 取模(余数) SELECT MOD(10, 3) AS 结果;(返回 1)

四、日期函数(处理时间日期)

以 MySQL 为例:

函数 作用 示例
NOW() 获取当前日期时间 SELECT NOW() AS 当前时间;(返回 2026-01-14 10:30:00)
CURDATE() 获取当前日期 SELECT CURDATE() AS 当前日期;(返回 2026-01-14)
CURTIME() 获取当前时间 SELECT CURTIME() AS 当前时间;(返回 10:30:00)
DATE_FORMAT() 格式化日期 SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日') AS 格式化日期;(返回 2026 年 01 月 14 日)
DATEDIFF() 计算两个日期差值 SELECT DATEDIFF('2026-01-20', '2026-01-14') AS 天数差;(返回 6,单位:天)
DATE_ADD() 日期加减 SELECT DATE_ADD(CURDATE(), INTERVAL 7 DAY) AS 一周后;(返回 2026-01-21)SELECT DATE_ADD(CURDATE(), INTERVAL -1 MONTH) AS 一个月前;(返回 2025-12-14)

五、条件函数(逻辑判断)

1. IF 函数(MySQL)
sql 复制代码
-- 语法:IF(条件, 满足条件返回值, 不满足返回值)
SELECT name, score, IF(score >= 60, '及格', '不及格') AS 成绩状态 FROM exam;
2. CASE WHEN(通用所有数据库)
sql 复制代码
-- 语法1:简单CASE
SELECT name, 
       CASE class 
           WHEN '高一(1)班' THEN '一班'
           WHEN '高一(2)班' THEN '二班'
           ELSE '其他班级' 
       END AS 班级简称
FROM students;

-- 语法2:搜索CASE(更灵活)
SELECT name, score,
       CASE 
           WHEN score >= 90 THEN '优秀'
           WHEN score >= 80 THEN '良好'
           WHEN score >= 60 THEN '及格'
           ELSE '不及格' 
       END AS 成绩等级
FROM exam;

六、NULL 处理函数

空值(NULL)是 SQL 中极易踩坑的点,这类函数专门解决 NULL 的判断和替换问题,所有数据库通用。

函数 作用 示例
IS NULL / IS NOT NULL 判断是否为空值 SELECT name FROM students WHERE phone IS NULL;(查询手机号为空的学生)SELECT name FROM students WHERE email IS NOT NULL;(查询邮箱非空的学生)
IFNULL()(MySQL)/ ISNULL()(SQL Server) 替换 NULL 值 SELECT name, IFNULL(phone, '未填写') AS 手机号 FROM students;(手机号为空则显示 "未填写")
COALESCE()(通用) 返回第一个非 NULL 值 SELECT name, COALESCE(phone, email, '无联系方式') AS 联系方式 FROM students;(优先取手机号,无则取邮箱,都无则显示 "无联系方式")
NULLIF()(通用) 若两个值相等返回 NULL,否则返回第一个值 SELECT NULLIF(score, 0) AS 有效分数 FROM exam;(分数为 0 则返回 NULL,否则返回分数)

示例

sql 复制代码
-- 统计有效订单数(排除金额为NULL或0的订单)
SELECT COUNT(COALESCE(NULLIF(amount, 0), NULL)) AS 有效订单数 FROM `order`;

七、转换函数:CAST & CONVERT(主流数据库通用)

转换函数主要分两类:CAST()(ANSI SQL 标准,跨数据库通用)和 CONVERT()(部分数据库扩展,支持格式定制),优先用 CAST() 保证兼容性,需要格式控制时用 CONVERT()

1. 通用语法
函数 语法 适用场景
CAST() CAST(待转换值 AS 目标类型) 简单类型转换,跨数据库通用
CONVERT() MySQL:CONVERT(待转换值, 目标类型)SQL Server:CONVERT(目标类型, 待转换值, 格式码) MySQL 中与 CAST 等价;SQL Server 中可定制日期 / 数字格式
2. 支持的常见目标类型

不同数据库的类型名称略有差异,核心常用类型如下:

类型大类 MySQL SQL Server PostgreSQL
数值类型 INT, DECIMAL(M,D), FLOAT INT, DECIMAL(M,D), FLOAT INTEGER, NUMERIC(M,D), FLOAT
字符串类型 CHAR(N), VARCHAR(N) CHAR(N), VARCHAR(N) CHAR(N), VARCHAR(N)
日期时间类型 DATE, DATETIME, TIMESTAMP DATE, DATETIME, SMALLDATETIME DATE, TIMESTAMP, TIMESTAMPTZ
生产级实战示例(按场景分类)
场景 1:数值 ↔ 字符串转换(最常用)

解决 "字符串数字无法计算""数字拼接文字" 问题:

sql 复制代码
-- 1. 字符串转数字(计算订单金额)
-- 场景:order_amount字段是VARCHAR类型,需求和
SELECT CAST(order_amount AS DECIMAL(10,2)) * 0.9 AS 折扣金额 FROM `order`;

-- 2. 数字转字符串(拼接备注)
-- 场景:将数值型的用户ID拼接成"用户-1001"格式
SELECT CONCAT('用户-', CAST(user_id AS CHAR)) AS 用户标识 FROM user;

-- 3. SQL Server定制格式(数字转带千分位的字符串)
SELECT CONVERT(VARCHAR(20), 123456.78, 1) AS 格式化金额; -- 返回 123,456.78
场景 2:字符串 ↔ 日期时间转换(开发高频)

解决 "字符串日期无法排序 / 筛选" 问题:

sql 复制代码
-- 1. 字符串转日期(筛选指定时间段订单)
-- MySQL
SELECT * FROM `order` 
WHERE CAST(order_date_str AS DATE) BETWEEN '2026-01-01' AND '2026-01-14';

-- SQL Server(指定格式码,避免解析错误)
-- 格式码 120:YYYY-MM-DD HH:MI:SS;111:YYYY/MM/DD
SELECT * FROM `order`
WHERE CONVERT(DATETIME, order_date_str, 120) >= '2026-01-01 00:00:00';

-- 2. 日期转字符串(格式化展示)
-- MySQL:将DATETIME转为"YYYY年MM月DD日"格式
SELECT DATE_FORMAT(CAST(create_time AS DATETIME), '%Y年%m月%d日') AS 创建时间 FROM user;

-- PostgreSQL(用::操作符简写)
SELECT create_time::DATE AS 创建日期 FROM user; -- 日期转字符串(默认格式)
场景 3:特殊类型转换
sql 复制代码
-- 1. NULL值处理(转换时避免NULL导致失败)
-- 场景:将可能为NULL的字符串字段转为数字,NULL则返回0
SELECT CAST(IFNULL(score_str, '0') AS INT) AS 分数 FROM exam;

-- 2. 布尔值转换(PostgreSQL/MySQL)
-- MySQL:BOOL本质是TINYINT,TRUE=1,FALSE=0
SELECT CAST(TRUE AS CHAR) AS 布尔转字符串; -- 返回 '1'

-- PostgreSQL:布尔值转字符串
SELECT CAST(TRUE AS VARCHAR) AS 布尔转字符串; -- 返回 't'
常见错误与避坑指南

转换失败报错:比如将非数字字符串(如 '123a')转为 INT,会直接报错。

解决方案:先过滤无效值

sql 复制代码
-- MySQL:用REGEXP判断是否为纯数字
SELECT 
  CASE WHEN score_str REGEXP '^[0-9]+$' THEN CAST(score_str AS INT) ELSE 0 END AS 分数
FROM exam;

日期格式不匹配:不同数据库对日期字符串的解析规则不同(比如 MySQL 支持 '2026-01-14',但不支持 '01/14/2026' 直接转换)。

解决方案:先统一日期格式,再转换

sql 复制代码
-- MySQL:先替换分隔符,再转日期
SELECT CAST(REPLACE('01/14/2026', '/', '-') AS DATE) AS 转换后日期;

精度丢失:DECIMAL 转 FLOAT 可能丢失精度,优先用 CAST (DECIMAL AS CHAR) 再处理。

转换函数是保证数据类型统一的核心工具:

优先用CAST() :遵循 ANSI 标准,跨数据库兼容性更好;需要格式定制时用CONVERT()(仅 SQL Server/MySQL);

转换前做校验:对非标准值(如 NULL、含特殊字符的字符串)先过滤 / 替换,避免转换失败;

注意类型匹配:日期转换要保证字符串格式与数据库解析规则一致,数值转换要避免精度丢失。

八、窗口函数

普通聚合函数(SUM/COUNT/AVG)会将多行数据合并为一行(比如统计每个部门的总销售额,结果只有部门 + 总额),而窗口函数的核心是:

不合并行,在保留原有行数据的基础上,对指定范围(窗口)的数据做聚合 / 排名计算。

这解决了开发中 "既要显示明细,又要显示统计值" 的高频需求(比如:显示每个员工的销售额,同时显示该员工在部门内的排名、部门总销售额)。

窗口函数的基础语法

窗口函数的通用结构分为两部分,核心是 OVER() 子句(定义 "窗口" 范围):

sql 复制代码
<窗口函数> OVER (
  [PARTITION BY 分组字段]  -- 可选,按指定字段分组(类似GROUP BY,但不合并行)
  [ORDER BY 排序字段 ASC/DESC]  -- 可选,对窗口内的数据排序
  [ROWS/RANGE BETWEEN 边界1 AND 边界2]  -- 可选,定义窗口的行范围(比如"前1行到当前行")
)

窗口函数的分类及实战示例

窗口函数主要分 3 大类,覆盖 90% 的业务场景,以下以 MySQL 8.0 + 为例(PostgreSQL/SQL Server 语法一致):

1. 排名类窗口函数(排行榜 / 名次统计必备)

最常用的 3 个排名函数,核心区别是 "如何处理并列名次":

函数 作用 特点 示例场景
ROW_NUMBER() 生成连续唯一排名 无并列,即使值相同,排名也不同(1,2,3,4) 生成不重复的员工销售额排名
RANK() 生成排名 有并列,并列后跳过后续名次(1,2,2,4) 竞赛排名(并列第 2 后,下一个是第 4)
DENSE_RANK() 生成密集排名 有并列,并列后不跳过后续名次(1,2,2,3) 等级统计(如:A 级、B 级,并列不影响后续等级)

实战示例:按销售额给部门内员工排名

sql 复制代码
-- 准备测试数据
CREATE TABLE employee (
  dept VARCHAR(20),  -- 部门
  name VARCHAR(20),  -- 姓名
  sales INT          -- 销售额
);
INSERT INTO employee VALUES
('销售部', '张三', 10000),
('销售部', '李四', 8000),
('销售部', '王五', 8000),
('技术部', '赵六', 5000),
('技术部', '钱七', 6000);

-- 核心查询:显示每个员工的3种排名
SELECT
  dept,
  name,
  sales,
  ROW_NUMBER() OVER (PARTITION BY dept ORDER BY sales DESC) AS rn,  -- 连续排名
  RANK() OVER (PARTITION BY dept ORDER BY sales DESC) AS rk,        -- 跳级排名
  DENSE_RANK() OVER (PARTITION BY dept ORDER BY sales DESC) AS drk  -- 密集排名
FROM employee;

查询结果(直观对比 3 种排名):

dept name sales rn rk drk
销售部 张三 10000 1 1 1
销售部 李四 8000 2 2 2
销售部 王五 8000 3 2 2
技术部 钱七 6000 1 1 1
技术部 赵六 5000 2 2 2
2. 聚合类窗口函数(累计 / 分组统计必备)

将 SUM/COUNT/AVG/MIN/MAX 等聚合函数作为窗口函数,实现 "不合并行的聚合统计",开发中最常用的是累计求和和分组总/ 均值。

实战场景 1:统计每个用户的累计订单金额

sql 复制代码
-- 准备订单数据
CREATE TABLE `order` (
  user_id INT,
  order_date DATE,
  amount DECIMAL(10,2)
);
INSERT INTO `order` VALUES
(1, '2026-01-01', 100.00),
(1, '2026-01-02', 200.00),
(1, '2026-01-03', 150.00),
(2, '2026-01-01', 300.00);

-- 核心查询:按用户分组、日期排序,计算累计金额
SELECT
  user_id,
  order_date,
  amount,
  SUM(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS total_amount  -- 累计求和
FROM `order`;

查询结果

user_id order_date amount total_amount
1 2026-01-01 100.00 100.00
1 2026-01-02 200.00 300.00
1 2026-01-03 150.00 450.00
2 2026-01-01 300.00 300.00

实战场景 2:显示每个员工销售额 + 部门总销售额 + 部门均值

sql 复制代码
SELECT
  dept,
  name,
  sales,
  SUM(sales) OVER (PARTITION BY dept) AS dept_total,  -- 部门总销售额
  AVG(sales) OVER (PARTITION BY dept) AS dept_avg     -- 部门平均销售额
FROM employee;
偏移类窗口函数(环比 / 相邻数据对比必备)

用于获取 "当前行的上一行 / 下一行" 数据,核心解决 "环比增长""前后数据对比" 问题,常用函数:

LAG(字段, n, 默认值):获取当前行前 n 行的字段值(n 默认 1,默认值可选)

LEAD(字段, n, 默认值):获取当前行后 n 行的字段值

实战场景:计算每日销售额的环比增长(当日 - 前日)

sql 复制代码
-- 准备日销售额数据
CREATE TABLE daily_sales (
  sale_date DATE,
  amount DECIMAL(10,2)
);
INSERT INTO daily_sales VALUES
('2026-01-01', 1000),
('2026-01-02', 1200),
('2026-01-03', 900);

-- 核心查询:计算环比
SELECT
  sale_date,
  amount,
  LAG(amount, 1, 0) OVER (ORDER BY sale_date) AS prev_amount,  -- 前日销售额
  amount - LAG(amount, 1, 0) OVER (ORDER BY sale_date) AS diff  -- 环比差值
FROM daily_sales;
查询结果
sale_date amount prev_amount diff
2026-01-01 1000 0 1000
2026-01-02 1200 1000 200
2026-01-03 900 1200 -300
窗口函数的避坑要点

版本兼容:MySQL 8.0 + 才支持窗口函数,5.7 及以下版本需用子查询 / 变量替代;

PARTITION BY vs GROUP BY:

GROUP BY:合并行,结果集行数 = 分组数;

PARTITION BY:不合并行,结果集行数 = 原表行数;

ORDER BY 的影响:

聚合类窗口函数加ORDER BY:默认统计 "从分组第一行到当前行" 的聚合值(如累计求和);

不加ORDER BY:统计整个分组的聚合值(如部门总销售额);

性能优化 :对PARTITION BYORDER BY的字段建立索引,可大幅提升窗口函数执行效率。

窗口函数是处理复杂统计的核心工具,关键要点:

核心优势:不合并行,同时保留明细和统计值,解决 "明细 + 统计" 的高频业务需求;

三大类场景:排名类(ROW_NUMBER/RANK)、聚合类(SUM/AVG OVER)、偏移类(LAG/LEAD)覆盖 90% 的统计需求;

核心语法OVER()子句中,PARTITION BY分组,ORDER BY排序,按需组合即可实现复杂统计。

前三大常用函数的总结

聚合函数 是统计分析的核心,重点掌握COUNT/SUM/AVG/MAX/MIN,需结合GROUP BY使用;

字符串 / 数值 / 日期函数 需注意不同数据库的语法差异(如 SQL Server 用LEN()替代LENGTH());

条件函数IF/CASE WHEN)是实现业务逻辑判断的关键,CASE WHEN兼容性更强,推荐优先使用。

相关推荐
chuxinweihui2 小时前
MySQL数据库基础
数据库·mysql
袁慎建@ThoughtWorks2 小时前
ThreadLocal那些事儿
java·jdk·多线程·threadlocal
专注于大数据技术栈2 小时前
java学习--HashSet
java·学习·哈希算法
菜鸟233号2 小时前
力扣518 零钱兑换II java实现
java·数据结构·算法·leetcode·动态规划
扶苏-su2 小时前
Java--标准输入输出流
java·开发语言
szm02253 小时前
Spring
java·后端·spring
无敌的牛3 小时前
MySQL基础
数据库·mysql
进阶的小名3 小时前
[超轻量级延时队列(MQ)] Redis 不只是缓存:我用 Redis Stream 实现了一个延时MQ(自定义注解方式)
java·数据库·spring boot·redis·缓存·消息队列·个人开发
短剑重铸之日3 小时前
《7天学会Redis》Day 6 - 内存&性能调优
java·数据库·redis·缓存·7天学会redis