业务开发中的多级查询---树形表查询方法

432 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

这篇文章主要介绍树形表的查询方法,主要提到自连接与递归查询两种方法。关于属性表结构应用举例如下:

举个例子:形象一点就类似于掘金首页那样的分类嘛,掘金首页看成根节点,根节点下面又有前端、后端这些二级节点,二级节点下面又有其他三级节点,就这样一级一级的。

image.png 那到底什么是树形表结构?

现在来看这张表:前端开发节点是1-1,它的父节点是1,HTML/CSS是节点1-1-1,父节点是1-1。我们可以理解成根节点1下有1-1、1-2、1-3...这样一些一级节点,而一级节点1-1下面又有1-1-1、1-1-2...这样一些二级节点。类似这样的,就是我们说的树形表结构。

image.png

我们想查询像这样的一张表(查询两个级别的节点)的数据,应该怎么做呢?
首先第一种方法就是用表的自连接:

SELECT * 
FROM course_category one INNER JOIN course_category two 
on one.id = two.parentid;

查询结果:

image.png 现在这样看着不太舒服,我们优化一下。

SELECT  one.id     one_id,
		    one.name   one_name,
		    one.label  one_label,
		    two.id     two_id,
		    two.name   two_name,
		    two.label  two_label
FROM course_category one 
		INNER JOIN course_category two on one.id = two.parentid 
WHERE one.parentid='1'
		AND one.is_show='1' 
		AND two.is_show='1'
ORDER BY one.orderby,two.orderby;

运行结果:

image.png 这样就看起来更清晰了。

当然有三级节点我们再加inner join嘛,当然这都是建立在需求固定的情况下,我们知道有几级节点。那如果需求不固定,这种自连接的方法就不太合适了。

那第二种方法就是mysql的递归,这种方式可以更灵活的查询树形结构。先来看它的语法结构(WITH语法):

WITH [RECURSIVE]
cte_name [(col_name [, col_name] ...)] AS (subquery)
[, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

语法中的RECURSIVE表示递归。举个简单的例子,查询5条记录:

with RECURSIVE t1 AS
(
    SELECT 1 as n
    UNION ALL
    SELECT n + 1 FROM t1 WHERE n < 5
)
SELECT * FROM t1;

t1 相当于一个表名, select 1相当于这个表的初始值,这里使用UNION ALL将初始值加入到表中。 n<5为递归执行的条件,当n>=5时结束递归调用,代码会输出1,2,3,4,5。

那用这种方法怎么实现我们的树形表递归查询呢?

WITH RECURSIVE t1 as
(
	select * from course_category p where id= '1'
	union all
	select t.* from course_category t inner join t1 on t1.id = t.parentid
)
select * from t1 order by t1.id, t1.orderby;

只要t1表节点下面有下属节点t1.id = t.parentid,就会一直往下查。这种是从根节点向下递归, 查询结果:

image.png

向上递归的查询:

with recursive t1 as (
select * from course_category p where id= '1-1-1'
union all
select t.* from course_category t inner join t1 on t1.parentid = t.id
)
select * from t1 order by t1.id, t1.orderby;

从1-1-1节点往上找,找父节点,直到查不到上级节点,结果如下:

image.png

文末碎语:

  • 本章要讲解的主要内容就到这里结束了🔚有哪些不懂的地方欢迎小伙伴们提问👏👏👏
  • 文中有任何不对的地方,欢迎大家指正🙏🙏🙏
  • 最后,感觉还不错的小伙伴,希望点个👍支持一下