MySQL CTE:解锁SQL查询新模式

目录

一、CTE 初相识

二、CTE 基础语法

(一)基本语法结构

(二)语法规则详解

三、非递归 CTE 应用实例

       (一)单 CTE 简单查询

(二)多 CTE 联合查询

四、递归 CTE 深入探索

(一)递归 CTE 原理剖析

(二)经典递归场景示例

五、CTE 与子查询的比较

(一)性能差异分析

(二)可读性和维护性对比

六、CTE 使用注意事项

(二)潜在问题及解决方案


一、CTE 初相识

在 MySQL 的世界里,当我们处理复杂的数据查询时,公用表表达式(Common Table Expressions,简称 CTE)就像是一位得力助手,悄然改变着我们编写 SQL 语句的方式。从 MySQL 8.0 版本开始,CTE 正式加入 MySQL 的大家庭,为开发者们提供了更强大、更灵活的数据处理能力。

那么,CTE 究竟是什么呢?简单来说,它是一个命名的临时结果集,仅在单个 SQL 语句(如 select、insert、delete 和 update)的执行范围内存在。我们可以把它想象成一个临时搭建的小舞台,在这个舞台上,我们可以进行各种数据的准备和预处理工作,而这些工作的成果只在当前 SQL 语句的 “表演” 中有效 。

举个简单的例子,假设我们要从一个员工表employees和部门表departments中查询每个部门的员工人数以及部门名称。如果不使用 CTE,我们可能会写出这样的子查询语句:

SELECT department_name,(SELECT COUNT(*) FROM employees e WHERE e.department_id = d.department_id) AS employee_count
FROM departments d;

这个查询虽然能得到我们想要的结果,但是子查询的结构使得代码的可读性和维护性都大打折扣。而且,当子查询变得复杂时,性能也会受到影响。

现在,让我们看看使用 CTE 如何实现同样的功能:

WITH employee_count_per_department AS (SELECT department_id,COUNT(*) AS employee_countFROM employeesGROUP BY department_id
)
SELECT d.department_name,ecpd.employee_count
FROM departments d
JOIN employee_count_per_department ecpd ON d.department_id = ecpd.department_id;

在这个例子中,我们首先使用WITH关键字定义了一个名为employee_count_per_department的 CTE,它计算了每个部门的员工人数。然后,在主查询中,我们直接引用这个 CTE,就像引用一个普通的表一样,将它与departments表进行连接,从而得到每个部门的名称和员工人数。

通过这个对比,我们可以发现,CTE 与子查询的不同之处在于:CTE 可以被多次引用,并且可以在不同的 CTE 之间相互引用,使得代码的结构更加清晰,逻辑更加连贯。同时,CTE 还可以提高 SQL 的性能,因为它可以避免在子查询中重复计算相同的结果。这就好比我们在搭建积木时,CTE 可以让我们把一些常用的积木组合先搭建好,然后在需要的时候直接拿过来使用,而不需要每次都重新搭建。

看到这里,你是不是已经对 CTE 产生了浓厚的兴趣?接下来,就让我们深入探索 CTE 的语法和更多强大的功能,一起揭开它神秘的面纱 。

二、CTE 基础语法

(一)基本语法结构

CTE 的基本语法结构围绕WITH关键字展开,其核心框架如下:

WITH cte_name AS (SELECT column1, column2,...FROM table_nameWHERE condition
)
SELECT column1, column2,...
FROM cte_name
WHERE another_condition;

在这个结构中,WITH关键字宣告了 CTE 的开始,它就像是一个 “开场哨”,告诉 MySQL 接下来要定义一个临时的结果集。cte_name是我们给这个临时结果集取的名字,就好比给一个新组建的团队取个响亮的队名,这个名字在后续的查询中会被用来引用这个 CTE。AS关键字则像是一个等号,用来连接 CTE 的名称和它的定义内容。

括号内的SELECT语句是 CTE 的核心内容,它定义了这个临时结果集的数据来源和筛选条件。这里的SELECT语句和我们平时写的普通查询语句类似,从指定的table_name中选择需要的列column1, column2,...,并通过WHERE条件筛选出符合要求的数据。

在定义好 CTE 之后,紧接着是一个主查询。主查询从cte_name中选择数据,就像从一个普通的表中查询数据一样,并且可以根据需要添加更多的筛选条件another_condition。

为了让大家更直观地理解,我们来看一个简单的示例。假设有一个students表,包含student_id(学生 ID)、student_name(学生姓名)、age(年龄)和grade(年级)等列,我们要查询年龄大于 18 岁的学生姓名和年级,使用 CTE 可以这样写:

WITH filtered_students AS (SELECT student_name, gradeFROM studentsWHERE age > 18
)
SELECT *
FROM filtered_students;

在这个例子中,filtered_students就是我们定义的 CTE,它从students表中筛选出年龄大于 18 岁的学生的姓名和年级。主查询则直接从filtered_students中选择所有列,获取我们想要的结果。

(二)语法规则详解

  1. CTE 名称的命名规则:CTE 名称必须遵循 MySQL 的标识符命名规则,首字符必须是字母、下划线(_)或美元符号($),后续字符可以是字母、数字、下划线或美元符号。例如,my_cte、cte_1都是合法的 CTE 名称,而1_cte则是不合法的。同时,在同一个WITH子句中,CTE 名称不能重复,否则 MySQL 会抛出错误,就像在一个班级里不能有两个相同名字的学生一样。
  2. 子查询的要求:CTE 定义中的子查询必须是一个有效的SELECT语句,它可以包含各种SELECT子句,如SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY等。但需要注意的是,子查询中不能包含FOR UPDATE和LOCK IN SHARE MODE语句,因为 CTE 是一个只读的临时结果集,不支持对数据进行锁定和更新操作。
  3. 在主查询中引用 CTE:在主查询中,我们可以像引用普通表一样引用 CTE。可以在FROM子句中直接使用 CTE 的名称,然后根据需要进行连接、筛选、聚合等操作。例如,我们可以在前面的例子基础上,对筛选出的学生按年级进行分组统计人数:
    WITH filtered_students AS (SELECT student_name, gradeFROM studentsWHERE age > 18
    )
    SELECT grade, COUNT(*) AS student_count
    FROM filtered_students
    GROUP BY grade;

    在这个查询中,主查询从filtered_students中选择数据,按grade列进行分组,并统计每个年级的学生人数。

    此外,我们还可以在一个WITH子句中定义多个 CTE,这些 CTE 之间可以相互引用。例如:

    WITH cte1 AS (SELECT column1, column2FROM table1
    ),
    cte2 AS (SELECT column3, cte1.column1FROM table2JOIN cte1 ON table2.id = cte1.id
    )
    SELECT *
    FROM cte2;

    在这个例子中,cte2引用了前面定义的cte1,通过这种方式,我们可以将复杂的查询逻辑分解成多个步骤,每个 CTE 负责一个特定的计算或筛选任务,使整个查询更加清晰和易于维护 。

    三、非递归 CTE 应用实例

       (一)单 CTE 简单查询

         假设我们有一个员工表employees,其中包含employee_id(员工 ID)、employee_name            (员工姓名)、department_id(部门 ID)和salary(工资)等字段。现在我们要查询                      department_id为 10 的所有员工信息,使用 CTE 可以这样实现:

WITH department_10_employees AS (SELECT employee_id, employee_name, department_id, salaryFROM employeesWHERE department_id = 10
)
SELECT *
FROM department_10_employees;

在这个例子中,我们首先定义了一个名为department_10_employees的 CTE,它从employees表中筛选出department_id为 10 的员工信息。然后在主查询中,直接从这个 CTE 中选择所有列,获取我们需要的员工数据。

这种单 CTE 简单查询的方式,使得代码结构更加清晰。我们可以将复杂的筛选条件封装在 CTE 中,主查询只需关注如何获取和展示数据。就好比我们在整理书架时,先把某一类书籍(如小说类)挑选出来放在一个临时的位置(CTE),然后再从这个临时位置挑选我们想要阅读的具体书籍(主查询获取数据)。

(二)多 CTE 联合查询

还是以员工表employees和部门表departments为例,departments表包含department_id(部门 ID)和department_name(部门名称)字段。现在我们要查询每个员工及其所在部门的平均工资,这就需要多个 CTE 联合使用了。

WITH employee_department AS (SELECT e.employee_id, e.employee_name, d.department_name, e.salaryFROM employees eJOIN departments d ON e.department_id = d.department_id
),
department_avg_salary AS (SELECT department_name, AVG(salary) AS avg_salaryFROM employee_departmentGROUP BY department_name
)
SELECT ed.employee_name, ed.department_name, das.avg_salary
FROM employee_department ed
JOIN department_avg_salary das ON ed.department_name = das.department_name;

在这个查询中,我们定义了两个 CTE。第一个employee_departmentCTE 通过连接employees表和departments表,获取每个员工的姓名、所在部门名称以及工资。第二个department_avg_salaryCTE 则基于employee_departmentCTE 的结果,计算每个部门的平均工资。最后,在主查询中,通过连接这两个 CTE,我们得到了每个员工及其所在部门的平均工资信息。

这种多 CTE 联合查询的方式,将复杂的查询逻辑分解成多个步骤。每个 CTE 专注于一个特定的计算或关联任务,使得整个查询过程更加清晰、易于理解和维护。就像搭建一座复杂的建筑,每个 CTE 就像是建筑中的一个模块,先分别构建好各个模块,然后再将它们组合在一起,形成一个完整的结构 。

四、递归 CTE 深入探索

(一)递归 CTE 原理剖析

递归 CTE 是 CTE 家族中的一个特殊成员,它允许在查询中引用自身,就像一个拥有 “自我复制” 能力的神奇工具,特别适用于处理具有层次结构的数据,如组织结构图、文件目录树、家族谱系等。其原理的核心在于巧妙地结合了种子查询(也称为锚成员)和递归查询(递归成员),并通过UNION [ALL]运算符将它们连接起来。

种子查询就像是递归旅程的起点,它是一个普通的查询语句,负责生成初始数据集。这个初始数据集是递归的基础,后续的递归操作都将基于它展开。例如,在查询员工上下级关系时,种子查询可以选择出公司的最高层级领导,作为整个递归查询的起始点。

递归查询则是这场旅程的 “推进器”,它不断引用 CTE 自身,通过与种子查询或上一次递归查询的结果进行关联,生成新的数据集。每一次递归,都会基于上一次的结果集进行扩展,就像在一棵树上不断长出新的枝叶。例如,在员工上下级关系的例子中,递归查询可以根据种子查询中选出的领导,找到其直接下属,然后再根据这些下属,找到他们的下属,以此类推,逐步构建出整个层级关系。

UNION [ALL]运算符在递归 CTE 中扮演着关键的角色,它负责将种子查询和递归查询的结果合并在一起。UNION会去除合并结果中的重复行,而UNION ALL则会保留所有行,包括重复行。在递归 CTE 中,通常使用UNION ALL,因为在处理层次结构数据时,重复行往往是有意义的,代表着不同层级之间的关联关系。而且,UNION ALL的性能通常比UNION更好,因为它不需要进行去重操作,减少了计算开销。

递归 CTE 的执行过程就像是一场层层递进的探索。首先,执行种子查询,得到初始结果集。然后,进入递归阶段,递归查询基于上一次的结果集进行计算,将新生成的结果与上一次的结果通过UNION [ALL]合并,形成新的结果集。这个过程会不断重复,直到递归查询不再返回新的数据,即满足了递归终止条件。例如,在员工上下级关系查询中,当所有层级的员工都被包含在结果集中,没有新的下属可以被找到时,递归终止 。

(二)经典递归场景示例

以员工上下级关系表为例,假设我们有一个employees表,包含employee_id(员工 ID)、employee_name(员工姓名)、manager_id(上级 ID)字段,现在我们要查询某个员工的所有上级。比如,我们要查询员工 ID 为 5 的所有上级,使用递归 CTE 可以这样实现:

WITH RECURSIVE manager_hierarchy AS (SELECT employee_id, employee_name, manager_idFROM employeesWHERE employee_id = 5 -- 初始条件,选择员工ID为5的记录作为种子UNION ALLSELECT e.employee_id, e.employee_name, e.manager_idFROM employees eINNER JOIN manager_hierarchy mh ON e.employee_id = mh.manager_id -- 递归条件,通过关联找到上级
)
SELECT *
FROM manager_hierarchy;

在这个查询中,种子查询部分SELECT employee_id, employee_name, manager_id FROM employees WHERE employee_id = 5选择出了员工 ID 为 5 的记录,作为递归的起始点。递归查询部分SELECT e.employee_id, e.employee_name, e.manager_id FROM employees e INNER JOIN manager_hierarchy mh ON e.employee_id = mh.manager_id通过将employees表与manager_hierarchy CTE 进行内连接,根据manager_id找到当前员工的上级,不断递归,直到没有上级为止。

如果我们要查询某个员工的所有下属,查询思路类似,只是递归条件中的关联关系变为根据当前员工的 ID 找到其下属的记录。例如,查询员工 ID 为 1 的所有下属:

WITH RECURSIVE subordinate_hierarchy AS (SELECT employee_id, employee_name, manager_idFROM employeesWHERE employee_id = 1 -- 初始条件,选择员工ID为1的记录作为种子UNION ALLSELECT e.employee_id, e.employee_name, e.manager_idFROM employees eINNER JOIN subordinate_hierarchy sh ON e.manager_id = sh.employee_id -- 递归条件,通过关联找到下属
)
SELECT *
FROM subordinate_hierarchy;

通过这些示例,我们可以看到递归 CTE 在处理层次结构数据时的强大功能,它能够简洁而高效地实现复杂的层级查询,帮助我们轻松地探索数据中的层级关系 。

五、CTE 与子查询的比较

 

(一)性能差异分析

在性能方面,CTE 和子查询有着不同的表现。从查询执行次数来看,子查询在主查询执行时,会根据其在查询语句中的位置和逻辑,被多次执行。例如,当子查询位于WHERE子句中,并且主查询对每一行数据都需要进行条件判断时,子查询可能会随着主查询的每一次行扫描而被执行一次。这就好比一个工人在完成一项任务时,需要不断地重复做同一件小事,效率自然不高。

而 CTE 在整个查询执行过程中,只会被计算一次。无论主查询引用它多少次,它都不会重新计算。这是因为 CTE 在执行前会被解析并生成一个临时结果集,后续的引用直接从这个临时结果集中获取数据。就像我们提前准备好了一份工具清单,在执行任务时,每次需要工具时都直接从清单中选取,而不需要重新去准备,大大提高了效率。

在资源占用方面,子查询的多次执行会导致更多的 CPU 资源被消耗,因为每次执行都需要进行查询解析、数据检索等操作。同时,由于可能会多次扫描相关表,也会增加磁盘 I/O 的负担。如果子查询的结果集较大,还会占用较多的内存来存储中间结果。

CTE 虽然也会占用一定的资源来生成临时结果集,但由于其只计算一次,在资源利用上相对更高效。尤其是当 CTE 的结果集被多次引用时,其资源优势更加明显。不过,如果 CTE 的定义中包含复杂的计算或大量数据的筛选,生成临时结果集的过程可能会消耗较多资源,但从整体查询执行的角度来看,后续的多次引用可以避免重复计算带来的资源浪费 。

(二)可读性和维护性对比

通过实际代码示例,我们能更直观地感受到 CTE 在提高查询可读性和维护性方面的优势。假设我们有一个电商数据库,其中包含orders表(订单表,包含order_id、customer_id、order_date、total_amount等字段)和customers表(客户表,包含customer_id、customer_name、contact_email等字段)。现在我们要查询每个客户的订单总金额以及客户的联系方式,并且只显示订单总金额大于 1000 的客户信息。

如果使用子查询,代码可能如下:

SELECT sub.customer_name,sub.contact_email,sub.total_amount
FROM (SELECT c.customer_id,c.customer_name,c.contact_email,SUM(o.total_amount) AS total_amountFROM customers cJOIN orders o ON c.customer_id = o.customer_idGROUP BY c.customer_id, c.customer_name, c.contact_email) sub
WHERE sub.total_amount > 1000;

在这个子查询中,我们首先在子查询内部进行了客户和订单表的连接,以及按客户分组计算订单总金额的操作。然后在主查询中,从子查询的结果中筛选出订单总金额大于 1000 的记录。这种嵌套结构使得代码的阅读和理解变得困难,尤其是当子查询内部的逻辑更加复杂时,我们需要从内到外逐步解析代码的含义。

现在,让我们看看使用 CTE 如何实现同样的功能:

WITH customer_order_summary AS (SELECT c.customer_id,c.customer_name,c.contact_email,SUM(o.total_amount) AS total_amountFROM customers cJOIN orders o ON c.customer_id = o.customer_idGROUP BY c.customer_id, c.customer_name, c.contact_email
)
SELECT cos.customer_name,cos.contact_email,cos.total_amount
FROM customer_order_summary cos
WHERE cos.total_amount > 1000;

使用 CTE 时,我们首先定义了一个名为customer_order_summary的 CTE,在这个 CTE 中完成了客户和订单表的连接以及订单总金额的计算。然后在主查询中,直接从这个 CTE 中获取数据,并进行筛选。这种结构使得代码的逻辑更加清晰,每个部分的功能一目了然。如果我们需要修改计算订单总金额的逻辑,或者调整筛选条件,只需要在对应的 CTE 或主查询部分进行修改,而不会影响到其他部分,大大提高了代码的维护性 。

六、CTE 使用注意事项

一)适用版本说明

CTE 是从 MySQL 8.0 版本开始引入的强大功能,这意味着如果你的 MySQL 版本低于 8.0,很遗憾,你将无法使用 CTE 来优化你的查询。就像你拥有一辆老式汽车,却无法安装最新的高科技导航系统一样。在这种情况下,你只能继续使用传统的子查询等方式来实现数据查询和处理。

所以,在决定使用 CTE 之前,请务必确认你的 MySQL 版本。你可以通过以下命令来查看当前 MySQL 的版本:

SELECT VERSION();

如果你的版本低于 8.0,并且希望使用 CTE 带来的便利,那么考虑升级你的 MySQL 版本是一个不错的选择。不过,在升级之前,一定要做好数据备份和测试工作,确保升级过程不会对现有业务造成影响。

(二)潜在问题及解决方案

  1. 递归 CTE 的无限循环问题:在使用递归 CTE 时,设置正确的终止条件至关重要。如果终止条件设置不当,就可能导致无限循环。例如,在查询员工上下级关系时,如果没有正确判断递归的结束点,就会出现一直递归下去的情况,这不仅会消耗大量的系统资源,还可能导致数据库崩溃。为了避免这种情况,我们必须确保递归查询中有明确的终止条件。比如在之前查询员工上级的示例中,当没有找到更高层级的上级时,递归就应该停止。同时,我们可以通过LIMIT语句来限制递归的深度,防止因数据异常导致的无限递归。例如:
WITH RECURSIVE manager_hierarchy AS (SELECT employee_id, employee_name, manager_idFROM employeesWHERE employee_id = 5UNION ALLSELECT e.employee_id, e.employee_name, e.manager_idFROM employees eINNER JOIN manager_hierarchy mh ON e.employee_id = mh.manager_idLIMIT 100 -- 限制递归深度为100
)
SELECT *
FROM manager_hierarchy;

  1. CTE 结果集过大问题:如果 CTE 生成的结果集非常大,可能会占用大量的内存和磁盘空间,影响查询性能。例如,当我们使用 CTE 对一个包含数百万条记录的表进行复杂的聚合操作时,生成的临时结果集可能会超出系统的承载能力。为了解决这个问题,我们可以尽量减少 CTE 中不必要的列选择,只选择查询中真正需要的列。同时,可以考虑对 CTE 的结果进行适当的筛选和分组,减少数据量。例如,在计算每个部门的平均工资时,如果部门表非常大,我们可以先在 CTE 中对部门表进行必要的筛选,只保留需要计算平均工资的部门数据:

WITH filtered_departments AS (SELECT department_id, department_nameFROM departmentsWHERE department_name LIKE '某特定部门%' -- 筛选特定部门
),
department_avg_salary AS (SELECT fd.department_id, fd.department_name, AVG(e.salary) AS avg_salaryFROM filtered_departments fdJOIN employees e ON fd.department_id = e.department_idGROUP BY fd.department_id, fd.department_name
)
SELECT *
FROM department_avg_salary;
  1. CTE 名称冲突问题:在同一个WITH子句中,CTE 的名称必须是唯一的,否则会导致语法错误。就像在一个班级里不能有两个完全相同名字的学生一样,在 SQL 查询的这个 “小世界” 里,每个 CTE 也都要有独一无二的名字。例如,以下代码就会因为 CTE 名称冲突而报错:
WITH cte AS (SELECT column1, column2FROM table1
),
cte AS ( -- 这里的cte名称与上面冲突SELECT column3, column4FROM table2
)
SELECT *
FROM cte;

为了避免这个问题,在定义 CTE 时,一定要仔细检查名称,确保每个 CTE 都有一个独特且有意义的名字,这样不仅能避免错误,还能让代码更易于理解和维护 。

喜欢作者的可以关注微信公众号,一起开启开发之旅吧!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/10661.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#,入门教程(12)——数组及数组使用的基础知识

上一篇: C#,入门教程(11)——枚举(Enum)的基础知识和高级应用https://blog.csdn.net/beijinghorn/article/details/123917587https://blog.csdn.net/beijinghorn/article/details/123917587 数组是一种数据集合,是一组…

【leetcode练习·二叉树】计算完全二叉树的节点数

本文参考labuladong算法笔记[拓展:如何计算完全二叉树的节点数 | labuladong 的算法笔记] 如果让你数一下一棵普通二叉树有多少个节点,这很简单,只要在二叉树的遍历框架上加一点代码就行了。 但是,力扣第第 222 题「完全二叉树的…

低代码系统-产品架构案例介绍、轻流(九)

轻流低代码产品定位为零代码产品,试图通过搭建来降低企业成本,提升业务上线效率。 依旧是从下至上,从左至右的顺序 名词概述运维层底层系统运维层,例如上线、部署等基础服务体系内置的系统能力,发消息、组织和权限是必…

对顾客行为的数据分析:融入2+1链动模式、AI智能名片与S2B2C商城小程序的新视角

摘要:随着互联网技术的飞速发展,企业与顾客之间的交互方式变得日益多样化,移动设备、社交媒体、门店、电子商务网站等交互点应运而生。这些交互点不仅为顾客提供了便捷的服务体验,同时也为企业积累了大量的顾客行为数据。本文旨在…

MSA Transformer

过去的蛋白质语言模型以单个序列为输入,MSA Transformer以多序列比对的形式将一组序列作为输入。该模型将行和列注意力交织在输入序列中,并在许多蛋白质家族中使用mask语言建模目标进行训练。模型的性能远超过了当时最先进的无监督学习方法,其…

QT实现有限元软件操作界面

本系列文章致力于实现“手搓有限元,干翻Ansys的目标”,基本框架为前端显示使用QT实现交互,后端计算采用Visual Studio C。 本篇将二维矩形截面梁单元(Rect_Beam2D2Node)组成的钢结构桥作为案例来展示软件功能。 也可以…

推荐一款好用的翻译类浏览器扩展插件

给大家推荐一款实用的翻译工具——沉浸式翻译。这是一款免费、高效的AI驱动浏览器扩展插件,能够帮助用户轻松打破语言障碍,享受沉浸式的阅读体验。 主要特性 沉浸式阅读体验:通过智能识别网页主内容区域并进行双语对照翻译,让用户…

ElasticSearch-文档元数据乐观并发控制

文章目录 什么是文档?文档元数据文档的部分更新Update 乐观并发控制 最近日常工作开发过程中使用到了 ES,最近在检索资料的时候翻阅到了 ES 的官方文档,里面对 ES 的基础与案例进行了通俗易懂的解释,读下来也有不少收获&#xff0…

开源的瓷砖式图像板系统Pinry

简介 什么是 Pinry ? Pinry 是一个开源的瓷砖式图像板系统,旨在帮助用户轻松保存、标记和分享图像、视频和网页。它提供了一种便于快速浏览的格式,适合喜欢整理和分享多种媒体内容的人。 主要特点 图像抓取和在线预览:支持从网页…

Java 大视界 -- Java 大数据在自动驾驶中的数据处理与决策支持(68)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

【数据结构】初识链表

顺序表的优缺点 缺点: 中间/头部的插入删除,时间复杂度效率较低,为O(N) 空间不够的时候需要扩容。 如果是异地扩容,增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗。 扩容可能会存在…

I.MX6ULL 中断介绍上

i.MX6ULL是NXP(原Freescale)推出的一款基于ARM Cortex-A7内核的微处理器,广泛应用于嵌入式系统。在i.MX6ULL中,中断(Interrupt)是一种重要的机制,用于处理外部或内部事件,允许微处理…

4-图像梯度计算

文章目录 4.图像梯度计算(1)Sobel算子(2)梯度计算方法(3)Scharr与Laplacian算子4.图像梯度计算 (1)Sobel算子 图像梯度-Sobel算子 Sobel算子是一种经典的图像边缘检测算子,广泛应用于图像处理和计算机视觉领域。以下是关于Sobel算子的详细介绍: 基本原理 Sobel算子…

苍穹外卖——数据统计

在商家管理端的左侧,有一个名为"数据统计"的菜单,该页面负责展示各个维度的数据统计,分别是营业额统计、用户统计、订单统计、销量排名top10。统计的数据是借助一些图形化的报表技术来生成并展示的。在左上角还可选择时间段&#x…

优盘恢复原始容量工具

买到一个优盘,显示32mb,我见过扩容盘,但是这次见到的是缩容盘,把2g的容量缩成32MB了,首次见到。。用芯片查询工具显示如下 ChipsBank(芯邦) CBM2199E 使用以下工具,恢复原始容量。。 其他CMB工具可能不行…

Flutter Candies 一桶天下

| | | | | | | | 入魔的冬瓜 最近刚入桶的兄弟,有责任心的开发者,对自己的项目会不断进行优化,达到最完美的状态 自定义日历组件 主要功能 支持公历,农历,节气,传统节日,常用节假日 …

[Collection与数据结构] B树与B+树

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…

ROS应用之SwarmSim在ROS 中的协同路径规划

SwarmSim 在 ROS 中的协同路径规划 前言 在多机器人系统(Multi-Robot Systems, MRS)中,SwarmSim 是一个常用的模拟工具,可以对多机器人进行仿真以实现复杂任务的协同。除了任务分配逻辑以外,SwarmSim 在协同路径规划方…

新鲜速递:DeepSeek-R1开源大模型本地部署实战—Ollama + MaxKB 搭建RAG检索增强生成应用

在AI技术快速发展的今天,开源大模型的本地化部署正在成为开发者们的热门实践方向。最火的莫过于吊打OpenAI过亿成本的纯国产DeepSeek开源大模型,就在刚刚,凭一己之力让英伟达大跌18%,纳斯达克大跌3.7%,足足是给中国AI产…

【Rust自学】15.5. Rc<T>:引用计数智能指针与共享所有权

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.5.1. 什么是Rc<T> 所有权在大部分情况下都是清晰的。对于一个给定的值&#xff0c;程序员可以准确地推断出哪个变量拥有它。 …