通过sql实现查树结构的所有子级或父级

 前提

主要利用find_in_set函数,还有就是:=操作符;
不了解的可以去了解一下这两个东西的作用,这里简单说一下:
find_in_set 就是判断以逗号拼接的字符串中是否包含某个字符串,例如 find_in_set('a','a,b,c'),返回的是a在后边集合中的位置,这里就是1了;
:=:意思是设置值,再增改查中都是一样,比如 select @num:=@num+1 ,就是设置num值递增1。

查询所有子集

SELECT
 code,  --orgCode
 PK_ORG, --主键id
 name , --orgName
 ischild --是否子级
FROM
 (
 SELECT
  t1.code,
  t1.PK_ORG,
  t1.name,
 IF
  ( find_in_set( pk_fatherorg, @pids ) > 0, @pids := concat( @pids, ',', PK_ORG ), '0' ) AS ischild  --pk_fatherorg:父级id
 FROM
  ( SELECT code, PK_ORG, name, pk_fatherorg FROM jthr.org_orgs t WHERE dr = 0 ORDER BY code ) t1, --dr:删除标记
  ( SELECT @pids := #{param.pkOrg} ) t2 --@pids:入参,即要查询的组织机构id
 ) t3 
WHERE
 ischild != '0' or PK_ORG = #{param.pkOrg} -- (带本级)
 -- ischild != '0'(不带本级)
 

具体解释以下这个sql,其中难以理解的是在 IF(find_in_set(pk_fatherorg, @pids) > 0, @pids := concat(@pids, ',', PK_ORG), '0') AS ischild,这块理解了这个sql就不复杂了,我们先来看以下几个函数

FIND_IN_SET(str, strlist)

  • str: 要查找的字符串。
  • strlist: 由逗号分隔的字符串列表。

返回值

  • 如果 str 在 strlist 中,则返回其位置(从1开始计数)。
  • 如果 str 不在 strlist 中,则返回0。
  • 如果 str 或 strlist 为 NULL,则返回 NULL。

IF(find_in_set(pk_fatherorg, @pids) > 0, ... , ...):

  • IF 函数用于条件判断。
  • 条件部分是 find_in_set(pk_fatherorg, @pids) > 0,即检查 pk_fatherorg 是否存在于 @pids 中。
  • 如果条件为真(即 pk_fatherorg 存在于 @pids 中),执行第一个参数。
  • 如果条件为假(即 pk_fatherorg 不存在于 @pids 中),执行第二个参数

@pids := concat(@pids, ',', PK_ORG):

  • 如果 pk_fatherorg 存在于 @pids 中,将当前记录的 PK_ORG 添加到 @pids 中。
  • concat(@pids, ',', PK_ORG) 将 @pids 和 PK_ORG 用逗号连接起来。
  • @pids := 将连接后的结果赋值给 @pids 变量。

理解完函数的具体意义后,这段sql就容易理解了,首先是find_in_set函数判断父级id是否是我们传的id,如果是,则是我们要查的子级,将其拼接到@pids里,这样我们的@pids就是我们的入参加上其子级的集合,依次向下遍历,即可得到完整的数据

注意:此处还需注意order by排序字段,有层级字段最好拿层级字段

我们还可以使用 WITH RECURSIVE 函数实现

WITH RECURSIVE org_tree (PK_ORG,CODE,NAME)
     AS (
         -- 初始查询:找到初始组织机构
         SELECT PK_ORG,CODE,NAME
         FROM jthr.org_orgs
         WHERE dr = '0' and PK_ORG = #{param.pkOrg}
         UNION ALL
         -- 递归查询:找到子组织机构
         SELECT cd.PK_ORG,cd.CODE,cd.NAME
         FROM jthr.org_orgs cd
         JOIN org_tree dt ON cd.pk_fatherorg = dt.PK_ORG)
SELECT PK_ORG,CODE,NAME
FROM org_tree
ORDER BY CODE

 WITH RECURSIVE org_tree (orgCode) 是 SQL 中定义递归公共表表达式(Recursive Common Table Expression, Recursive CTE)的一部分。它用于处理层次结构或树状数据。它允许你在查询中定义一个递归的公共表表达式,具体来说,WITH RECURSIVE 通常分为两部分:

  • 初始查询:定义递归的起点,即最顶层的数据。
  • 递归查询:定义如何从当前层级的数据中获取下一层级的数据,直到没有更多的数据可以递归为止。

当前sql中,函数具体含义:

  • WITH RECURSIVE:关键字,表示这是一个递归查询。
  • org_tree (PK_ORG,CODE,NAME):定义了一个名为 org_tree 的临时表(CTE),并且指定了该表的三个列 PK_ORG,CODE,NAME。

查询所有父级 

SELECT
	code,
 PK_ORG,
 name ,
	isParent
FROM
	(
	SELECT
		t1.code,
  t1.PK_ORG,
  t1.name,
	IF
		( find_in_set( PK_ORG, @ids ) > 0, @ids := concat( @ids, ',', pk_fatherorg ), '0' ) AS isParent 
	FROM
		( SELECT code, PK_ORG, name, pk_fatherorg FROM jthr.org_orgs t WHERE dr = 0 ORDER BY code desc) t1,
		( SELECT @ids := #{param.pkOrg} ) t2 
	) t3 
WHERE
	isParent != '0';

同样可以使用 WITH RECURSIVE 函数实现

-- 查询所有父分类
with RECURSIVE org_tree (PK_ORG,CODE,NAME,pk_fatherorg)
as (
    select PK_ORG,CODE,NAME,pk_fatherorg 
		from jthr.org_orgs  
		where dr = '0' and PK_ORG = #{param.pkOrg}
    union all
    select t.PK_ORG,t.CODE,t.NAME,t.pk_fatherorg
    from jthr.org_orgs t
             inner join org_tree t2 on t.PK_ORG = t2.pk_fatherorg
)
select
    PK_ORG,CODE,NAME,pk_fatherorg
from org_tree;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值