MySQL 8.0 WITH子句详解:从基础语法到递归CTE优化

你回想一下,早几年写稍微复杂一点的分析SQL,是不是每次都得先建临时表、再join几层子查询,到了第三层嵌套自己都看不下去?MySQL 8.0的通用表达式(WITH)出来后,这个问题基本算是翻篇了。我最早接触CTE其实是在业务报表里,当时一段长达两百行的嵌套子查询被逐步改写成多个WITH模块,不但执行流程清爽了,连后续加指标都省了大半力气。这篇文章想从实际使用的角度,把MySQL 8.0里WITH子句的基本语法、普通CTE的用法、递归CTE的实现原理以及性能优化注意点系统梳理一遍,重点侧重可复现的操作细节和踩坑记录,适合正在学习MySQL进阶特性、或者准备把老项目迁移到8.0的同学参考。

1. 从“能跑就行”到“优雅查询”:为什么值得下功夫学 WITH

1.1 一个改变我写SQL习惯的示例

最开始用CTE,是因为接手了一个报表模块,那段核心SQL长这样:一个大查询里套了两层临时子查询,每个子查询又各自引用上一层的聚合结果,结构几乎是三层嵌套。改动需求加个同比字段,我在里面调了两小时,改完都觉得只是碰巧能跑。后来我尝试用WITH重写,每个中间结果集独立成一块,再拼回主查询,意外的收获是:整体逻辑变得像搭积木,每一块命名清楚,后面维护的人不用再沿着括号往里钻。

这里放个简化版对比。假设要统计每个分类下销量Top3的商品:

-- 旧方案:嵌套子查询 SELECT t1.category_name, t1.goods_name, t1.sales_amount FROM ( SELECT c.name AS category_name, g.name AS goods_name, SUM(g.amount) AS sales_amount FROM goods_sales g JOIN category c ON g.category_id = c.id GROUP BY c.id, g.id ) t1 WHERE ( SELECT COUNT(*) FROM ( SELECT c2.id, g2.id, SUM(g2.amount) AS s2 FROM goods_sales g2 JOIN category c2 ON g2.category_id = c2.id GROUP BY c2.id, g2.id ) t2 WHERE t2.id = t1.category_id AND t2.s2 > t1.sales_amount LIMIT 1 ) = 0;

再换成CTE版本:

WITH sales_summary AS ( SELECT c.id AS category_id, c.name AS category_name, g.id AS goods_id, g.name AS goods_name, SUM(g.amount) AS sales_amount FROM goods_sales g JOIN category c ON g.category_id = c.id GROUP BY c.id, g.id ) SELECT s.category_name, s.goods_name, s.sales_amount FROM sales_summary s LEFT JOIN sales_summary s2 ON s2.category_id = s.category_id AND s2.sales_amount > s.sales_amount WHERE s2.category_id IS NULL;

是不是一眼就能看懂?这就是CTE最大的价值:它把SQL拆成逻辑清晰的模块,命名即文档,阅读顺序就是业务处理顺序,大括号地狱从此不存在了。

1.2 它解决的痛点和适用人群

通用表达式本质上是给SQL增加了一个命名的临时结果集概念。但临时结果集并不只存在于执行期——WITH在生成执行计划时就已经被优化器识别,可以被当作可复用的标准子结构进行优化。这一点和“直接创建临时表”完全不是一个思路。

这个特性尤其适合几类场景:

  • 复杂报表:多指标需要基于同一份明细多次聚合,用WITH定义一次底层数据,后面所有分组都引用它。
  • 层级数据:组织架构、菜单树、物料BOM清单,这些天然带上下级关系的数据,配合递归写法能一条SQL解决。
  • 数据清洗:ETL过程中多步处理,比如先过滤、再去重、再算指标,每一步都用WITH表达,逻辑全部留在最终SQL里,审计起来也清楚。
  • 老SQL重构:旧项目里大量嵌套子查询和临时表,逐步替换为CTE后,可维护性提升非常明显。

2. WITH 子句的核心语法拆解,照着写就行

2.1 基础语法与执行特点

MySQL 8.0的WITH语法,官方描述为:

WITH cte_name [(column_name_list)] AS ( SELECT ... ) SELECT ...

CTE可以单独存在,也可以多个连续定义,中间用逗号分隔。后面的CTE可以使用前面已经定义的CTE,但是前面的CTE不能反向引用后面的CTE,这是逻辑上的顺序依赖。

一个容易忽略的点:CTE列名可以在主体内显式指定,别名并不总是必须写在SQL子句内部。比如:

WITH revenue_cte (dept_id, total_revenue) AS ( SELECT dept_id, SUM(revenue) FROM sales_data GROUP BY dept_id ) SELECT * FROM revenue_cte;

这种做法在主体查询列名不清晰、或者聚合函数列名过长时特别好用,还能顺便统一下游引用的字段名。

多个CTE定义连写时,可以这样组织:

WITH base_data AS ( SELECT id, product_id, sale_amount, sale_time FROM order_detail WHERE sale_time >= '2024-01-01' ), dept_summary AS ( SELECT d.manager_id, SUM(b.sale_amount) AS total FROM base_data b JOIN dept d ON b.dept_id = d.id GROUP BY d.manager_id ) SELECT * FROM dept_summary;

这里第二CTE直接引用了第一个CTE,而且两个CTE模块的命名都表达了数据阶段,执行时像流水线一样一层层传递数据,整个链条很干净。

2.2 派生表和 WITH 的差异,别搞混

派生表就是from后面的括号子查询,它也能实现类似数据集的效果,但二者有三个关键差别:

  • 可读性:派生表必须把结果内联在主查询括号里,无法单独命名被多次引用;CTE可以多次引用同一逻辑,且模块可以重复出现在多个后续位置。
  • 可复用性:CTE在同一个语句里可以引用多次。派生表如果被反复引用,意味着那段子查询要重复写,语句膨胀且容易出错。
  • 执行计划差异:CTE在优化器中的处理与物化、合并策略相关,MySQL8.0的优化器会评估CTE是否需要物化;而派生表虽然也会被优化,但代码层没法直接控制复用的粒度。

我遇到过这样一个案例:统计各部门销售额以及全公司销售额占比。用派生表写,公司总额那个子查询要重复写两遍,不仅冗长,还必须保持两边同步。用CTE就不一样了:

WITH dept_total AS ( SELECT dept_id, SUM(sale_amount) AS total FROM sales_detail GROUP BY dept_id ), grand_total AS ( SELECT SUM(total) AS all_total FROM dept_total ) SELECT d.dept_id, d.total, ROUND(d.total / g.all_total * 100, 2) AS pct FROM dept_total d CROSS JOIN grand_total g ORDER BY pct DESC;

这里dept_total被多次引用,CTE做到了“一次定义,多处使用”,维护成本直线降低。

提示:如果CTE只在主查询里引用一次,那它在语义上其实和派生表没太大差别。这时选择哪个,主要就看阅读是否方便。追求极致性能时,简单场景下不必为了“用特性而用特性”强上CTE。

3. 递归 CTE 的进阶玩法:让层级查询不再痛苦

3.1 递归是怎么工作的:三个关键部件

MySQL 8.0支持WITH RECURSIVE,也就是递归CTE。理解了它,很多树形结构查询都能用一个SQL搞定。

递归CTE的标准结构,包含三个部分:

WITH RECURSIVE cte AS ( -- 初始查询:anchor member,产生递归起点 SELECT id, name, parent_id FROM organization WHERE parent_id IS NULL UNION ALL -- 递归查询:recursive member,逐层向下扩展 SELECT o.id, o.name, o.parent_id FROM cte JOIN organization o ON o.parent_id = cte.id ) SELECT * FROM cte;

初始查询先取根节点,递归查询负责把当前层级的子节点找到,然后不断重复,直到JOIN不到任何新数据为止。整个递归过程类似“广度优先展开”。

UNION和UNION ALL的选择要特别注意:UNION会去重,避免出现重复行,逻辑上更安全;UNION ALL性能更好,但如果数据本身有环(比如父节点指向孩子再指向祖先),不加控制就会无限递归。实际业务数据里环并不常见,但自引用表的历史数据很容易出现脏数据,所以生产环境要权衡。

3.2 实操案例:组织架构与层级路径

假设有员工表:

CREATE TABLE employees ( id INT PRIMARY KEY, name VARCHAR(50), manager_id INT NULL );

现在需要输出每个员工的完整汇报链路,比如“王总 > 李经理 > 张三”,并且要求同时算出层级深度。递归CTE可以这样写:

WITH RECURSIVE emp_path AS ( SELECT id, name, manager_id, name AS path_str, 1 AS depth FROM employees WHERE manager_id IS NULL UNION ALL SELECT e.id, e.name, e.manager_id, CONCAT(ep.path_str, ' > ', e.name), ep.depth + 1 FROM employees e JOIN emp_path ep ON e.manager_id = ep.id ) SELECT id, name, depth, path_str FROM emp_path ORDER BY depth, id;

运行结果会得到从顶层到每个节点的完整路径。上面这个SQL在生产项目里可以直接用于导出组织架构树、汇报线展示、甚至权限继承的模拟。

如果你要反向查询某个节点的所有子节点,也一样简单,只要把递归方向调换,从指定节点往下找即可。这里不放代码了,核心思路就是把锚点换成指定id,递归部分把父和子关系反过来。

3.3 防止无限递归:常见限制手段

MySQL的递归CTE默认有个循环次数限制,cte_max_recursion_depth,默认值1000,用于防止异常情况下无限执行。这个参数对很多表不够用,比如深层级组织架构可能超过1000层,那就需要按实际情况调高。

调整方式:

SET SESSION cte_max_recursion_depth = 5000;

这个参数是会话级的,不会立刻影响其他事务,安全性较好。如果出现报错“Recursive query aborted after 1001 iterations”,第一反应先看是不是真是层级深导致,第二反应再看是否有环路数据。如果是脏数据形成环,调大参数只能延长超时,正确做法是修数据或加访止条件。

注意:递归中如果发现某条路径反复出现相同节点,基本就是数据环了。可以在递归查询里加一个node_path字段,用FIND_IN_SET判断当前节点是否已经出现过,若出现则终止扩展。这是一个省事的防御性写法。

4. 实操过程:用 WITH 优化复杂查询的全流程记录

4.1 典型场景:商品类目汇总与环比分析

竞赛环节里,我们用一个模拟场景完整走一遍优化流程。业务需求:统计每个一级类目下各子类目的销售额,以及该子类目在上月同期的销售额,最终只输出当月排名前三的子类目。

原始SQL结构:

SELECT c1.id AS cat1_id, c1.name AS cat1_name, c2.id AS cat2_id, c2.name AS cat2_name, SUM(o.amount) AS cur_month_amount FROM orders o JOIN category c2 ON o.cat2_id = c2.id JOIN category c1 ON c2.parent_id = c1.id WHERE o.create_time BETWEEN '2025-03-01' AND '2025-03-31' GROUP BY c1.id, c2.id ORDER BY cur_month_amount DESC LIMIT 3;

这是只算当月数据的情况。如果加上上月同期的销售额,查找对应的上月订单明细,势必造成大量重复扫描。我当时的改造方法是,先用WITH把订单明细拆成“当月”和“上月”两个模块,再分别聚合,最后join。

首先定义两个CTE:

WITH cur_month_orders AS ( SELECT cat2_id, SUM(amount) AS cur_amount FROM orders WHERE create_time >= '2025-03-01' AND create_time < '2025-04-01' GROUP BY cat2_id ), last_month_orders AS ( SELECT cat2_id, SUM(amount) AS last_amount FROM orders WHERE create_time >= '2025-02-01' AND create_time < '2025-03-01' GROUP BY cat2_id ) SELECT c1.id AS cat1_id, c1.name AS cat1_name, c2.id AS cat2_id, c2.name AS cat2_name, COALESCE(cur.cur_amount, 0) AS cur_month_amount, COALESCE(last.last_amount, 0) AS last_month_amount FROM category c2 JOIN category c1 ON c2.parent_id = c1.id LEFT JOIN cur_month_orders cur ON cur.cat2_id = c2.id LEFT JOIN last_month_orders last ON last.cat2_id = c2.id ORDER BY cur_month_amount DESC LIMIT 3;

这样重构后,订单表被扫描的次数从原来可能需要多次扫描,变成两次按不同时间段扫描聚合,目的明确、逻辑清晰,也给了优化器更明确的“二段式聚合”路径。

4.2 用执行计划验证优化效果

改造完成后,我用EXPLAIN FORMAT=TREE看了一眼执行计划,CTE部分被标记为具体的子节点,能直观看到优化器是把它当作物化临时结果还是作为视图合并处理。

MySQL 8.0的优化器对CTE有“合并”和“物化”两种策略。如果CTE简单,优化器多半会把它合并到外层查询;如果CTE结构复杂、被多次引用,优化器则可能将其物化为内部临时表。

实际测试中,我发现一个坑:如果CTE被多次引用且数据量很小时,物化成本反而更高。比如一个只有十几行结果的CTE被JOIN了5次,物化之后再扫描代价也不高;但如果是几百MB数据量的CTE被引用两次,物化带来的临时表IO开销就很明显。

这种情况下我的处理方式是,减少CTE引用次数,或者提前在下层过滤条件做更彻底的裁剪。也就是说,CTE内部能过滤就过滤,别把全量明细带上来——这点和普通SQL优化思路完全一致。

4.3 参数层面的可调空间

递归CTE的迭代深度限制需要考虑,普通CTE同样需要关注tmp_table_size和max_heap_table_size。CTE物化产生的临时表如果没有足够的内存空间,就会落到磁盘,性能断崖下降。

我遇到过一张只有300万行的订单明细CTE,物化后临时表落盘,整个查询从0.3秒变成9秒。当时排查时看了状态变量Created_tmp_disk_tables,发现数量猛增。后来优化方案是给SQL增加前置过滤条件,让CTE内数据量从300万降到40万,临时表内存问题迎刃而解。

如果你在线上环境遇到CTE突然变慢,先查这两个状态变量:

SHOW SESSION STATUS LIKE 'Created_tmp_tables'; SHOW SESSION STATUS LIKE 'Created_tmp_disk_tables';

根据落盘临时表数量的变化,能快速判断是不是物化了。

5. 常见问题与限制核对,看完少走弯路

5.1 频繁踩到的错误和排查思路

错误场景报错信息或表现形式排查方向
递归CTE超过深度限制Recursive query aborted after 1001 iterations检查cte_max_recursion_depth配置,或确认是否存在环
CTE名称冲突Every derived table must have its own alias确认CTE名称和表名、别名没有重复
引用顺序错误Unknown column ... in ...检查是否引用了一个尚未定义的CTE
递归成员引用非递归成员Invalid reference to recursion确认递归部分引用的表一定是CTE本身,而不是外部表
递归成员数据列不一致The column count of recursive query is not the same确认锚点和递归部分的SELECT列数一致,类型兼容
物化临时表落盘查询突然变慢,临时表落盘状态变量增长优化CTE内部过滤范围,或调整tmp_table_size

我特别提一下“The column count of recursive query is not the same”这个错误。递归CTE要求锚点查询和递归查询的列数量严格一致,同时列类型也要兼容。比如锚点是INT,递归部分拼接出了一个字符串,立刻报错。这是我在写组织架构路径时遇到的,解决方案是让锚点也输出相同类型的路径字段,保持结构一致。

5.2 递归 CTE 的生产使用建议

递归在数据量大的树状结构里执行效率并非总能如人意。每层迭代都需要进行一次表扫描加JOIN递归结果集,当树的深度到几十层时,即使每层数据量不大,总的开销也不小。

我之前测过一张约10万员工的BOM层级表,递归CTE查单条物料链路大约耗时几十毫秒,但一次性查询全量树的路径,代价就很高。生产环境数据画像如下:物料编码表约8万行,父子关系约15万条。全树展开路径的递归SQL执行时间约4秒,主要是迭代次数多,且每层都需要扫描整张关系表。

因此,线上使用递归CTE时,我有几个习惯:

  • 先确认业务数据的真实深度,并设置合理的cte_max_recursion_depth,而不是盲目调大。
  • 锚点尽量先做条件过滤,让递归的起点数据量尽量小,这样每一层JOIN规模都会小很多。
  • 如果只是统计层级数量和深度,考虑在应用层用程序遍历一次,再批量写入一张冗余表,比每次SQL递归要稳。
  • 涉及多级BOM的实时查询,建议用物化路径方案替代递归,别让数据库每条查询都做递归展开。

5.3 WITH 子句在 MySQL 8.0 的适用边界

通用表达式不是优化银弹,它有明确的适用边界。首先,MySQL 8.0中的WITH不是永久视图,每条语句内的CTE生命周期只属于那条语句,不能跨语句复用。其次,CTE内部的索引使用逻辑和正常表一样,如果CTE内部没有可用的索引,外层JOIN时的性能依然不好。第三,同一个查询里如果存在多个大CTE,且它们之间没有相互依赖,优化器可能会并行物化,这在资源紧张时会放大IO压力。

我还遇到过一个问题:CTE内LIKE查询无法利用索引的情况。后来在CTE内部加全文索引的思路也被执行计划否决了。最后我换了个做法,先建一张临时表,添加索引,再执行查询,反而更快。

这提醒我一点:CTE清晰表达的是逻辑关系,但物理优化层面,临时表的显式索引在某些场景比CTE贪图方便更值得依赖。CTE适合用来替代嵌套子查询、减少重复计算、增强查询可读性;而不适合无脑把所有业务都写成巨型WITH块,让优化器承担巨大压力。

6. 个人实操体会与一个小建议

如果只让我说一条最重要经验,那就是:CTE不是用来炫技的,它最大的价值是让复杂SQL具有可读性和可维护性。我见过有人把一个简单的两表JOIN也套上三个WITH,反而比直接JOIN更难读。做事要权衡。

另外一个非常值得推荐的小练习方式:从你自己的业务库里找一条最痛的三层子查询,把它改写成WITH版本,然后对比改写前后的执行时间和表扫描次数。不用刻意去建复杂的树形数据,普通报表数据就能体会它带来的结构便利。你之前觉得无从下手的SQL,改着改着就会有一种“原来还能这么写”的通透感。

MySQL 8.0的通用表达式确实给日常开发带来了不少便利,但真正用好它,还是要把注意力放在业务逻辑和数据特性上。SQL写得好不好,归根结底是逻辑是否清晰、数据是否被合理利用,工具特性只是辅助。希望这篇文章能帮你少踩一点坑,把WITH子句用到真正该用的地方。

相关新闻

S7-1200与博途V16在生物发酵控制系统中的实施经验

S7-1200与博途V16在生物发酵控制系统中的实施经验

做自动化这些年&#xff0c;液体、流量、温控项目接过不少&#xff0c;但真正让人睡不踏实的&#xff0c;还是生物发酵这一类。罐子里养的是活物&#xff0c;微生物不会等我把PID调完再繁殖&#xff0c;迟到一小时&#xff0c;整罐料可能就废了。制药厂对批次记录、灭菌温度曲线…

2026/10/20 8:12:29 阅读更多 →
SpringBoot插件化架构实战:原理、接入与避坑指南

SpringBoot插件化架构实战:原理、接入与避坑指南

SpringBoot项目做大了以后&#xff0c;总会出现一种尴尬&#xff1a;功能越来越多&#xff0c;发布却越来越慢&#xff1b;客户需求千奇百怪&#xff0c;又不能每个都单独维护一套分支。我去年负责的中台系统就是这样&#xff0c;每次大促前加一个营销小功能&#xff0c;都要跟…

2026/10/20 8:12:29 阅读更多 →
端侧大脑实战:移动机器人本地闭环的模型压缩与推理优化

端侧大脑实战:移动机器人本地闭环的模型压缩与推理优化

去年有一段时间&#xff0c;我负责的一个移动操作机器人项目——内部代号“灵境智源”——出了个很尴尬的问题&#xff1a;机器人识别工件要靠云端服务&#xff0c;网络一抖&#xff0c;整条机械臂就像被人掐住脖子一样僵在半空&#xff0c;等云端把结果发回来&#xff0c;工件…

2026/10/20 8:12:29 阅读更多 →

最新新闻

C# Windows服务开发全攻略:从生命周期到调试部署

C# Windows服务开发全攻略:从生命周期到调试部署

用C#写Windows服务程序&#xff0c;这件事听起来像是一个“上古时代”的开发任务&#xff0c;但实际上只要你做过任何需要长时间后台运行、脱离用户会话独立工作的功能——比如数据同步、文件监控、定时报表推送——Windows服务就是绕不开的选项。C#在这方面成熟度极高&#xf…

2026/10/20 9:40:21 阅读更多 →
AI Agent架构设计对比:OpenClaw与OpenCode的工程实践

AI Agent架构设计对比:OpenClaw与OpenCode的工程实践

1. 从两个开源项目的设计分歧说起AI Agent 这个词在过去一年被用得太泛了。但凡能调个 API、能读个文件、能跑个循环&#xff0c;都敢叫自己 Agent。但真正落到架构设计层面&#xff0c;不同项目之间的差异其实非常大——大到什么程度&#xff1f;大到你对"Agent 到底是什…

2026/10/20 9:40:21 阅读更多 →
代码大模型周报:仓库级理解与推理效率优化论文精选

代码大模型周报:仓库级理解与推理效率优化论文精选

1. 这周代码大模型圈子里值得细看的三篇论文每周追代码大模型方向的论文&#xff0c;最头疼的不是找不到论文&#xff0c;而是找到的太多、太杂&#xff0c;不知道哪些值得花时间精读。我自己的习惯是每周固定花两三个小时&#xff0c;把主要来源的更新过一遍&#xff0c;筛出三…

2026/10/20 9:40:21 阅读更多 →
STM32CubeIDE V2.0.0实战:嵌入式开发工具链的集成与调试效率提升

STM32CubeIDE V2.0.0实战:嵌入式开发工具链的集成与调试效率提升

做嵌入式开发这些年&#xff0c;我几乎把主流的工具链都摸过一遍&#xff0c;从早期用第三方编译器配合外部烧录工具&#xff0c;到后来各家芯片厂商自己出IDE&#xff0c;说实话折腾的过程里踩了不少坑。STM32CubeIDE这个工具&#xff0c;我算是从它刚推出就一路用过来的&…

2026/10/20 9:40:21 阅读更多 →
AI大模型时代Java与大数据开发者的能力升级与实战路径

AI大模型时代Java与大数据开发者的能力升级与实战路径

最近不少讨论都围绕一个话题&#xff1a;AI 大模型到底会不会抢走程序员的饭碗。尤其是做 Java、大数据的同学&#xff0c;焦虑感往往更强。因为网上的声音总是很极端——一边说“Java 已经过时了&#xff0c;赶紧转 AI”&#xff0c;另一边说“大模型只是玩具&#xff0c;企业…

2026/10/20 9:40:21 阅读更多 →
OpenClaw 自动化任务编排框架:部署、配置与运维实战指南

OpenClaw 自动化任务编排框架:部署、配置与运维实战指南

1. 项目概述与核心定位OpenClaw 这个项目&#xff0c;我在几个不同的环境里前后部署过不下十次&#xff0c;从最早期的版本一路跟到现在的稳定分支&#xff0c;踩过的坑和积累的经验足够写一本小册子。简单来说&#xff0c;OpenClaw 是一个开源的自动化任务编排与执行框架&…

2026/10/20 9:39:16 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →