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

SQL 函数从入门到精通:原理、类型、窗口函数与实战指南

SQL 函数从入门到精通:原理、类型、窗口函数与实战指南

面向初学者的由浅入深教程:带你理解 SQL 函数的本质、分类(标量/聚合/窗口)、内置与自定义函数的用法差异,配合 MySQL 与 PostgreSQL 的完整示例与避坑建议。


目录

  • SQL 函数从入门到精通:原理、类型、窗口函数与实战指南
    • 一、什么是 SQL 函数?
    • 二、函数类型与使用场景
    • 三、内置函数速览(以 MySQL/PG 为例)
    • 四、自定义函数:MySQL 与 PostgreSQL 对比
      • 1)MySQL 自定义函数(Stored Function)
      • 2)PostgreSQL 自定义函数(plpgsql)
    • 五、聚合函数与自定义聚合(PG)
    • 六、窗口函数实战
    • 七、性能与可维护性
    • 八、安全与规范
    • 九、常见坑与避坑
    • 十、实践清单(建议)
    • 附:MySQL/PG 对照要点
    • 彩蛋:梗版总结(轻松读法)

一、什么是 SQL 函数?

  • 概念:SQL 函数是在查询或写入过程中被调用的可复用计算单元,输入参数,返回计算结果。
  • 价值:解耦复杂计算、提升可读性、复用公共逻辑、在数据库端高效执行(减少应用端搬运与二次计算)。
  • 与存储过程的区别:函数偏“返回值计算”,适合在 SELECTWHEREORDER BYCHECK 等处嵌入;过程偏“执行动作”,更多用于批量更新、事务流程。

二、函数类型与使用场景

  • 标量函数(Scalar):输入若干值,返回单个标量值。适合清洗、格式化、业务规则判断。
  • 聚合函数(Aggregate):对多行汇总,返回单值,如 SUM/AVG/COUNT/MAX/MIN,也可自定义复杂聚合。
  • 窗口函数(Window):在不折叠行的前提下,基于窗口分区进行排名、累计、移动统计,如 ROW_NUMBER()LAG/LEADSUM() OVER(...)

常见场景:

  • 统一数据清洗(手机号脱敏、文本规范化)。
  • 指标计算(转化率、留存、同比环比)。
  • 排名、TopN、滑动窗口统计。

三、内置函数速览(以 MySQL/PG 为例)

  • 字符:LOWER/UPPER/TRIM/REPLACE/SUBSTRING/REGEXP_REPLACE(PG)
  • 数值:ROUND/CEIL/FLOOR/RANDOM(PG random(),MySQL RAND()
  • 日期:NOW()/CURRENT_DATE/DATE_TRUNC()(PG)/DATE_FORMAT()(MySQL)
  • 条件:COALESCE/NULLIF/CASE WHEN
  • JSON:JSON_EXTRACT()(MySQL)/jsonb_extract_path_text()(PG)

四、自定义函数:MySQL 与 PostgreSQL 对比

1)MySQL 自定义函数(Stored Function)

DELIMITER //
CREATE FUNCTION fn_mask_phone(p_phone VARCHAR(20))
RETURNS VARCHAR(20)
DETERMINISTIC
BEGINIF p_phone IS NULL OR LENGTH(p_phone) < 7 THENRETURN p_phone;END IF;RETURN CONCAT(LEFT(p_phone, 3), '****', RIGHT(p_phone, 4));
END //
DELIMITER ;-- 使用
SELECT fn_mask_phone('13812345678');

要点:

  • RETURNS 指定返回类型;DETERMINISTIC 表示相同输入恒定输出,利于优化。
  • 存储函数应避免修改数据(以免副作用),适合作为计算函数在查询中使用。

2)PostgreSQL 自定义函数(plpgsql)

CREATE OR REPLACE FUNCTION fn_mask_phone(p_phone TEXT)
RETURNS TEXT
LANGUAGE plpgsql AS $$
BEGINIF p_phone IS NULL OR length(p_phone) < 7 THENRETURN p_phone;END IF;RETURN left(p_phone, 3) || '****' || right(p_phone, 4);
END;
$$;-- 使用
SELECT fn_mask_phone('13812345678');

PG 还支持 LANGUAGE sqlLANGUAGE plpythonu 等多语言,常用 plpgsqlsql


五、聚合函数与自定义聚合(PG)

内置聚合:SUM/AVG/COUNT/MAX/MIN/STRING_AGG(PG)/GROUP_CONCAT(MySQL)。

在 PostgreSQL 中可以自定义聚合(MySQL 8.0 也引入了自定义聚合的扩展方式但较少使用):

-- 将文本拼接为逗号分隔
SELECT STRING_AGG(name, ',') FROM users; -- PG
SELECT GROUP_CONCAT(name) FROM users;    -- MySQL

PG 自定义聚合通常需要定义状态转换函数与最终函数,初学可先掌握内置聚合与窗口函数。


六、窗口函数实战

窗口函数不折叠行,适合排名、累计与环比。

-- 1) 分区排名
SELECT user_id,amount,ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY amount DESC) AS rn
FROM orders;-- 2) 累计/移动平均
SELECT stat_date,amount,SUM(amount) OVER (ORDER BY stat_date) AS cum_amount,AVG(amount) OVER (ORDER BY stat_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_7
FROM daily_revenue;-- 3) 同比/环比(LAG/LEAD)
SELECT stat_date,amount,LAG(amount, 1)  OVER (ORDER BY stat_date) AS prev,amount - LAG(amount, 1) OVER (ORDER BY stat_date) AS diff
FROM daily_revenue;

MySQL 与 PG 均支持窗口函数(MySQL 8.0+)。


七、性能与可维护性

  • 避免在可索引列上包裹函数,防止失去索引(非 SARGable)。
  • 将高开销函数计算前置到 WITH 子句或临时表,复用结果。
  • 小心非确定性函数(如随机、当前时间)对缓存与可重复性的影响。
  • 对自定义函数标注 IMMUTABLE/STABLE/VOLATILE(PG)或 DETERMINISTIC(MySQL)以利优化器。

八、安全与规范

  • 函数应无副作用,避免在函数内执行 DML 以免难以推导。
  • 最小权限:仅授予调用所需的 EXECUTE;敏感表走视图或安全函数封装。
  • 严格参数化与输入校验,杜绝动态 SQL 注入风险(PG 可用 format() 搭配 quote_ident/quote_literal)。

九、常见坑与避坑

  • WHERE 对列使用函数导致全表扫描。
  • 忘记标注函数稳定性,导致计划无法重用或错误优化。
  • 自定义函数里抛异常未捕获,影响批量任务;必要时在上层流程处理。
  • 混淆窗口与聚合:窗口不折叠行,聚合折叠行。

十、实践清单(建议)

  • 写一个手机号脱敏函数,并在用户列表中批量展示。
  • 用窗口函数计算过去 7 天的移动平均 GMV 与日环比。
  • 将复杂 CASE 逻辑提取为自定义函数,统一在多查询中使用。

附:MySQL/PG 对照要点

  • 非确定性与稳定性标注:MySQL DETERMINISTIC;PG IMMUTABLE/STABLE/VOLATILE
  • 字符函数命名差异:SUBSTRING 参数写法不同、正则函数差异。
  • JSON 操作函数不同:MySQL JSON_EXTRACT/->>,PG jsonb 运算符与函数族。
  • 窗口函数两者均支持,但语法细节与函数名存在差异。

如果你需要,我可以为这篇文章生成配套的 SQL 脚本与示例数据集,便于本地一键上手演示。


彩蛋:梗版总结(轻松读法)

  • 把函数想成“即食小零食”,随手一丢就有味(随处可用,返回一个值);
  • 聚合函数是“榨汁机”,把一堆水果打成一杯果汁(多行变一行);
  • 窗口函数是“吃着不减的自助餐”,既吃到单份菜又能看全场排名(不折叠行还排名统计);
  • 非 SARGable 就像“给跑鞋绑铅块”,索引跑不动;
  • IMMUTABLE/DETERMINISTIC 像给函数贴“保质期”,输入一样味道不变,厨子(优化器)才敢囤货(缓存计划)。

文章转载自:

http://IDjwNp7Q.tfwsk.cn
http://GP7ucVCQ.tfwsk.cn
http://zBOw5VuP.tfwsk.cn
http://LqjIVKzw.tfwsk.cn
http://mGiFVBJu.tfwsk.cn
http://VjJa473o.tfwsk.cn
http://ggFaamrJ.tfwsk.cn
http://k6ycetHp.tfwsk.cn
http://erPQPTet.tfwsk.cn
http://bDAhvusx.tfwsk.cn
http://isJjwsbR.tfwsk.cn
http://ftcMgtJu.tfwsk.cn
http://G3gkGzWt.tfwsk.cn
http://DPB9Uqcz.tfwsk.cn
http://EgY6gu0q.tfwsk.cn
http://egv06BuZ.tfwsk.cn
http://immn0BzS.tfwsk.cn
http://x00TzUhD.tfwsk.cn
http://1jPBz73d.tfwsk.cn
http://2StgZLR0.tfwsk.cn
http://osUzPEIR.tfwsk.cn
http://a5dqMjM1.tfwsk.cn
http://5k3J6TQC.tfwsk.cn
http://rDdfWDGS.tfwsk.cn
http://JDQk7t6C.tfwsk.cn
http://EGzOlmn4.tfwsk.cn
http://SIv1sMsn.tfwsk.cn
http://LMGJKwLB.tfwsk.cn
http://Hh7hQozi.tfwsk.cn
http://EJHlEwbJ.tfwsk.cn
http://www.dtcms.com/a/373704.html

相关文章:

  • 嵌入式 - ARM2
  • 【后端】阿里巴巴 Java 开发规范 —— 换行速查表
  • 基于 OpenCV 的信用卡数字识别:从原理到实现
  • 为什么要做智慧养老?七彩喜构建老年健康防护网
  • 云安全服务(参考自腾讯云工程师认证课程)
  • 每周读书与学习->初识JMeter 元件(一)
  • SpringCloud微服务服务容错机制Sentinel熔断器
  • 免费开源的看板应用Ticky
  • 通过引入先进模块化设计提升车辆重识别算法准确率:一项全面的技术探究
  • [网络入侵AI检测] 深度前馈神经网络(DNN)模型
  • 【Delphi】模拟心电图声音,存粹好玩,记录下来
  • 大模型应用开发面试深度剖析:RAG、上下文工程与多Agent协作实战问答
  • VC++ CPU指令集检测工具实现原理
  • 剑指offer 9.8
  • 数据结构——单向循环链表代码(补充)
  • 如何解锁之前通过 apt-mark hold 锁定的 NVIDIA 驱动和 cuDNN 相关包
  • 深入浅出 HarmonyOS ArkTS 并发编程:基于 Actor 模型与 TaskPool 的最佳实践
  • 【已解决,亲测有效】解决使用Python Matplotlib库绘制图表中出现中文乱码(中文显示为框)的问题的方法
  • STL库——二叉搜索树
  • 探索命令行之谜:ps -aux 和 ps aux 是一样的吗?
  • leetcode11(H 指数)
  • TensorRT自定义量化 对数量化
  • 【Python】S1 基础篇 P4 if 语句指南
  • 在使用ffmpeg与音转文模型时,会报错音转文stack expects a non-empty Tensor List
  • 苏州ecovadis认证500人内费用多少?
  • 基于Zigbee设计的楼宇环境监测系统_278
  • 利用ruoyi快速开发
  • 私有化部署Dify构建企业AI平台教程
  • 【CVPR2020】GhostNet:从廉价操作中获得更多特征
  • Java 接口 extends与 implements总结