适当的选择sql递归可以很有效的提高效率

简要描述:

当我们遇到一个需要通过递归查询才能实现的功能点时,首先想到的是代码递归去查询,但有时候我们会发现当树节点的层次比较多时,递归一次次的与数据库交互会一定程度的降低我们的程序性能(这还不包括一些节点子很功能的处理时间),基于此,我们可以考虑SQL递归,一次全查出来,或许能更好的的解决我们的问题。

问题情境:

设计了一张表,包含一个主键id,一个父ID,还有一些其他必要字段(简单说就是一个有树状结构的表),需要从这个表中查出某一个节点下所有直接子节点的id,然后用这个id获取一个表对象,经过一系列的计算与逻辑处理在将这些子节点的直接子节点查出来做同样的操作,直到查不到子节点为止。

问题解决:

根据问题情境很容易联想到代码的递归,先做查询在处理,一直递归下去,递归终止的条件就是查不到数据为止。实际开发过程中发现,这个递归很复杂,很耗时。因为不止一次的查询,查询出来的数据进行的逻辑处理不止有一些数据库交互还有很多耗时的接口调用,当数据量小时,速度还可以接受,但当树结构的层次变得很多时就会很慢。那么该如何解决这种问题呢?这里提供一个sql递归,一次性查出来一条分支的所有数据,然后用代码控制将最底层的数据计算结果一层层往上返回,最终得到根节点的计算结果。

废话不多说,下面是具体步骤:


首先上表结构

IDparentIDparam1param2param3level
A001(null)(null)(null)(null)0
A002A001(null)(null)(null)1
A003A001(null)(null)(null)1
A004A002(null)(null)(null)2
A005A002(null)(null)(null)2
A006A003(null)(null)(null)2
A007A003(null)(null)(null)2




表中有一个ID字段,一个parentID字段,三个参数字段,一个节点等级字段(根节点为0,二级节点为1,以此类推)。

以上表中数据为例,树状图如下:


我们的目的是计算A001的值,而A001需要A002和A003的结果来参与计算,A002又需要A004和A005的计算结果,A003又需要A006和A007的计算结果,所以我们的思路是将A001下的所有子节点查出来,然后根据节点等级倒序排序。代码处理是将最底层的节点的计算结果放到方法入口的一个map中,这个map是从A001开始传进来的,所以这个map经过计算之后会将A004和A005的结果带回给A002并重新塞一个A002 的值进去,然后再带回给A001,A003的结果也是这样带回去的,所以A001得到的map中就包含它的所有子节点的值,可以直接拿来参与运算。

这就是一套计算流程,下面介绍一下递归SQL的写法。

假设我们上面的那个表叫testTable,那么我们的SQL如下:

with temp(ID,parentID,param1,param2,param3,level) as 

(select ID,parentID,param1,param2,param3,level from testTable

where id ='A001'

union all

select A.ID,A.parentID,A.param1,A.param2,A.param3,A.level from testTable A ,temp B

 where A.parentID=B.ID

)

select * from temp A order by A.level desc;



ok,我们的处理最终经过测试,效率并不差,而且代码实现比较容易(相比于代码的递归),当我们遇到有递归需求的表时,并不一定使用代码来递归,其实适当的选择sql递归也是不错的选择哦。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL递归查询可以用来处理树形结构的数据,例如组织架构、商品分类等。在SQL Server中,可以使用Common Table Expression (CTE)来实现递归查询。 具体步骤如下: 1. 创建CTE,包含递归查询的初始部分 2. 定义递归查询的迭代部分 3. 合并初始部分和迭代部分,形成最终查询结果 下面是一个简单的例子,假设有一个员工表Employee,包含员工编号、姓名、上级编号等字段。我们要查询某个员工的所有下属,包括间接下属。 ``` WITH EmployeeHierarchy (EmpId, EmpName, ManagerId, [Level]) AS ( -- 初始部分,查询指定员工信息 SELECT EmpId, EmpName, ManagerId, 0 AS [Level] FROM Employee WHERE EmpId = @EmpId UNION ALL -- 迭代部分,查询下属信息 SELECT e.EmpId, e.EmpName, e.ManagerId, [Level] + 1 FROM Employee e JOIN EmployeeHierarchy eh ON e.ManagerId = eh.EmpId ) SELECT EmpId, EmpName, ManagerId, [Level] FROM EmployeeHierarchy ORDER BY [Level], EmpName ``` 在上面的例子中,我们使用CTE EmployeeHierarchy来实现递归查询。初始部分查询指定员工的信息,迭代部分查询指定员工的下属信息,这两部分通过UNION ALL合并。最终查询结果包含员工编号、姓名、上级编号和层级信息,并按照层级和姓名排序。 需要注意的是,递归查询可能会导致性能问题,因为它需要不断地扫描数据集。在实际应用中,应该避免过深的递归层数,以及使用合适的索引来优化查询性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值