mysql查找无根节点sql_SQL 双亲节点查找所有子节点的实现方法

怎么保存树状结构的数据呢?在 SQL 中常用的是双亲节点法。创建表如下

CREATE TABLE category ( id LONG, parentId LONG, name String(20) )

INSERT INTO category VALUES ( 1, NULL, 'Root' )

INSERT INTO category VALUES ( 2, 1, 'Branch1' )

INSERT INTO category VALUES ( 3, 1, 'Branch2' )

INSERT INTO category VALUES ( 4, 3, 'SubBranch1' )

INSERT INTO category VALUES ( 5, 2, 'SubBranch2' )

其中,parent id 表示父节点, name 是节点名称。

假设当前欲获取某一节点下所有子节点(获取后代 Descendants),该怎么做呢?如果使用程序(Java/PHP)递归调用,那么将在数据库与本地开发语言之间来回访问,效率之低可想而知。于是我们希望在数据库的层面就可以完成,——该怎么做呢?

递归法

经查询,最好的方法(个人觉得)是 SQL 递归 CTE 的方法。所谓 CTE 是 Common Table Expressison 公用表表达式的意思。网友评价说:“CTE 是一种十分优雅的存在。CTE 所带来最大的好处是代码可读性的提升,这是良好代码的必须品质之一。使用递归 CTE 可以更加轻松愉快的用优雅简洁的方式实现复杂的查询。”——其实我对 SQL 不太熟悉,大家谷歌下其意思即可。

怎么用 CTE 呢?我们用小巧数据库 SQLite,它就支持!别看他体积不大,却也能支持最新 SQL99 的 with 语句,例子如下。

WITH w1( id, parentId, name) AS

(SELECT

category.id,

category.parentId,

category.name

FROM

category

WHERE

id = 1

UNION ALL

SELECT

category.id,

category.parentId,

category.name

FROM

category JOIN w1 ON category.parentId= w1.id

)

SELECT * FROM w1;其中 WHERE id = 1 是那个父节点之 id,你可以改为你的变量。简单说,递归 CTE 最少包含两个查询(也被称为成员)。第一个查询为定点成员,定点成员只是一个返回有效表的查询,用于递归的基础或定位点。第二个查询被称为递归成员,使该查询称为递归成员的是对 CTE 名称的递归引用是触发。在逻辑上可以将 CTE 名称的内部应用理解为前一个查询的结果集。递归查询没有显式的递归终止条件,只有当第二个递归查询返回空结果集或是超出了递归次数的最大限制时才停止递归。递归次数上限的方法是使用 MAXRECURION。

c718129a0e7eb8263116e61f8d12b913.png

相应地给出查找所有父节点的方法(获取祖先 Ancestors,就是把 id 和 parentId 反过来)

WITH w1( id, parentId, name, level) AS

( SELECT

id,

parentId,

name,

0 AS level

FROM

category

WHERE

id = 6

UNION ALL

SELECT

category.id,

category.parentId,

category.name ,

level + 1

FROM

category JOIN w1 ON category.id= w1.parentId

)

SELECT * FROM w1;

无奈的 MySQL

SQLite ok 了,而 MySQL 呢?

在另一边厢,大家都爱用的 MySQL 却无视 with 语句,官网博客上明确说明是压根不支持,十分不方便,明明可以很简单事情为什么不能用呢?——而且 MySQL 也好像没有计划在将来的新版本中添加 with 的 cte 功能。于是大家想出了很多办法。其实不就是一个递归程序么——应该不难——写函数或者存储过程总该行吧?没错,的确如此,——写递归不是问题,问题是用 SQL 写就是个问题——还是那句话,“隔行如隔山”,虽然有点夸张的说法,但我想既懂数据库又懂各种数据库方言写法(存储过程)的人应该不是很多吧~,——不细究了,反正就是代码帖来贴去呗~

我这里就不贴 SQL 了,可以看这里的,《MySQL中进行树状所有子节点的查询》

至此,我们的目的可以说已经达到了,而且还不错,因为这是不限层数的(以前 CMS 常说的“无限级”分类)。——其实,一般情况下,层数超过三层就很多,很复杂了,一般用户如无特殊需求,也用不上这么多层。于是,在给定层数的约束下,可以写标准的 SQL 来完成该任务——尽管有点写死的感觉~~

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4

FROM category AS t1

LEFT JOIN category AS t2 ON t2.parentId = t1.id

LEFT JOIN category AS t3 ON t3.parentId = t2.id

LEFT JOIN category AS t4 ON t4.parentId = t3.id

WHERE t1.id= 1

a98b4859c3c41c8cb692f676614b2119.png

相应地给出查找所有父节点的方法(获取祖先 Ancestors,就是把 id 和 parentId 反过来)

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4

FROM category AS t1

LEFT JOIN category AS t2 ON t2.id= t1.parentId

LEFT JOIN category AS t3 ON t3.id= t2.parentId

LEFT JOIN category AS t4 ON t4.id= t3.parentId

WHERE t1.id= 10优化版本

但是生成的结果和第一个例子相比起来有点奇怪,而且不好给 Java 用,——那就再找找其他例子

SELECT

p1.id,

p1.name,

p1.parentId as parentId,

p2.parentId as parent2_id,

p3.parentId as parent3_id,

p4.parentId as parent4_id,

p5.parentId as parent5_id,

p6.parentId as parent6_id

FROM category p1

LEFT JOIN   category p2 on p2.id = p1.parentId

LEFT JOIN   category p3 on p3.id = p2.parentId

LEFT JOIN   category p4 on p4.id = p3.parentId

LEFT JOIN   category p5 on p5.id = p4.parentId

LEFT JOIN   category p6 on p6.id = p5.parentId

WHERE 1 IN   (p1.parentId,

p2.parentId,

p3.parentId,

p4.parentId,

p5.parentId,

p6.parentId)

ORDER BY 1, 2, 3, 4, 5, 6, 7; 这个总算像点样子了,结果是这样子的。

cfe5cd2162d892a995111bcdd9a7fc0d.png

相应地给出查找所有父节点的方法(获取祖先 Ancestors,就是把 id 和 parentId 反过来, 还有改改 IN 里面的字段名)

SELECT

p1.id,

p1.name,

p1.parentId as parentId,

p2.parentId as parent2_id,

p3.parentId as parent3_id

FROM category p1

LEFT JOIN category p2 on p2.parentId = p1.id

LEFT JOIN category p3 on p3.parentId = p2.id

WHERE 9 IN (p1.id,

p2.id,

p3.id)

ORDER BY 1, 2, 3;

这样就很通用啦~无论你 SQLite 还是 MySQL。

其他查询:

查询直接子节点的总数:

SELECT c.*

, (SELECT COUNT(*) FROM category c2 WHERE c2.parentId = c.id)

AS direct_children

FROM category c

•使用 with 语句递归,通俗易懂的例子(英文),我第一个成功的例子就是从这里 copy 的,另外还可以查层数 level 和反向的父节点:https://www.valentina-db.com/dokuwiki/doku.php?id=valentina:articles:recursive_query

•标准写法的出处(英文):http://stackoverflow.com/questions/20215744/how-to-create-a-mysql-hierarchical-recursive-query

•很好的总结贴(英文):http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

•SQlite with 语句用法中文翻译(太晦涩,不懂鸟) http://blog.csdn.net/aflyeaglenku/article/details/50978986

•利用闭包做的树结构(书上说这个方法最好,但同时觉得也很高级,英文)http://charlesleifer.com/blog/querying-tree-structures-in-sqlite-using-python-and-the-transitive-closure-extension/

以上这篇SQL 双亲节点查找所有子节点的实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

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

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

相关文章

一文看懂微服务背后的技术演进与应用实践

简介: 2021年7月2日,阿里云用户组(AUG)第一次线下活动在济南召开。阿里云云原生资深专家李国强结合自身微服务领域经验,现场跟数十家山东企业分享了云原生的代表技术之一“微服务”的演进和应用实践。本文根据作者的现…

1 分钟记住 docker 镜像和容器常用基本命令

作者 | xiaochuhe来源 | CSDN博客镜像常用基本命令查看自己服务器中docker 镜像列表docker images搜索镜像docker search 镜像名 docker search --filterSTARS9000 mysql 搜索 STARS >9000的 mysql 镜像拉取镜像docker pull 镜像名 docker pull 镜像名:tag运行镜像docker ru…

业界首个机密计算容器运行时—Inclavare Containers正式进入CNCF!

简介: Inclavare Containers 通过云原生计算基金会(CNCF)TOC 投票正式成为 CNCF 官方沙箱项目。 作者|彦荣 2021 年 9月 15 日,Inclavare Containers 通过云原生计算基金会(CNCF)TOC 投票正式成…

python 矩阵库_NumPy 矩阵库(Matrix)

NumPy 中包含了一个矩阵库 numpy.matlib,该模块中的函数返回的是一个矩阵,而不是 ndarray 对象。由 m n 个数aij排成的 m 行 n 列的数表称为 m 行 n 列的矩阵,简称 m n 矩阵。记作这 mn 个数称为矩阵 A的元素,简称为元&#xff…

顺丰科技 Hudi on Flink 实时数仓实践

简介: 介绍了顺丰科技数仓的架构,趟过的一些问题、使用 Hudi 来优化整个 job 状态的实践细节,以及未来的一些规划。 本文作者为刘杰,介绍了顺丰科技数仓的架构,趟过的一些问题、使用 Hudi 来优化整个 job 状态的实践细…

Paillier半同态加密:原理、高效实现方法和应用

简介: 《数据安全法》已于9月1日起正式实施,两个月后《个人信息保护法》也将开始施行,意味着数据安全和隐私保护方面的监管将会在年内陆续到位。在合规收紧大背景下,“数据孤岛”现象日渐明显。如何实现安全的数据流通&#xff0c…

django给mysql配主从_django中的mysql主从读写分离:一、配置mysql主从分离

一、配置mysql主从同步的步骤:(1) 在主服务器上,必须开启二进制日志机制和配置一个独立的ID(2) 在每一个从服务器上,配置一个唯一的ID,创建一个用来专门复制主服务器数据的账号(3) 在开始复制进程前,在主服务器上记录二…

从 40% 跌至 4%,“糊”了的 Firefox 还能重回巅峰吗?

作者 | 丁广辉 责编 | 张红月出品 | CSDN(ID:CSDNnews)Mozilla Firefox,通常简称为Firefox,中文名叫做火狐,是由Mozilla基金会及其子公司Mozilla公司开发的一款自由、开源的网页浏览器。2004年&#x…

如何发现 Kubernetes 中服务和工作负载的异常

简介: 本次分享为Kubernetes 监控公开课的第二节内容:如何发现 Kubernetes 中服务和工作负载的异常。 分享由三个部分组成: 一、Kubernetes 异常定位存在痛点; 二、针对这些痛点,Kubernetes 监控如何更快、更准、更全的…

内含干货PPT下载|一站式数据管理DMS及最新解决方案发布

简介: 今天主要给大家介绍一站式数据管理平台DMS以及解决方案的发布。议题包含企业数据管理当前的一些痛,DMS一站式数据管理平台以及其核心技术,实时数仓解决方案以及相应的应用实践。 “数聚云端智驭未来”——阿里云数据库创新上云峰会暨第…

java 数组数据类型_java基本数据类型和数组

第一类:逻辑型boolean第二类:文本型char第三类:整数型(byte、short、int、long)char类型占2个字节short从-32768到32767int从-2147483648,到2147483647共10位long从-9223372036854775808到9223372036854775807共19位第四类:浮点型(float、double)在数学中0到1有无数个浮点数&am…

kube-scheduler 磁盘调度源码分析

作者 | leadersnowy来源 | CSDN博客kube-scheduler介绍首先我们知道,kube-scheduler的根本工作任务是根据各种调度算法将Pod调度到最合适的工作节点上一、整个调度流程分为两个阶段:1、预选(Predicates):输入是所有节点…

开放搜索查询分析服务架构解读

简介: 搜索行为在后端都会有大量的数据计算和处理才会召回符合用户需求的搜索结果,本次分享结合自建搜索业务中查询分析服务常见的问题及难点,介绍阿里云开放搜索查询分析具备的能力及解决方案,并深度解读阿里巴巴查询分析服务架构…

多任务多目标CTR预估技术

简介: 多目标(Multi Objective Learning)是MTL中的一种。在业务场景中,经常面临既要又要的多目标问题。而多个目标常常会有冲突。如何使多个目标同时得到提升,是多任务多目标在真实业务场景中存在的意义。 作者 | 志阳…

Veeam 发布 2022 年数据保护趋势报告,开发者需关注哪些点?

如今数据作为重要的生产要素,成为数字经济高速发展的关键驱动力之一。越来越多开发者和企业认识到数据保护的重要性,关注数据保护发展趋势,以通过相关的技术解决方案来制定应对策略。 为帮助企业捋请思路,加快数字化转型步伐&…

blazeds调用java_Flex使用Blazeds与Java交互及自定义对象转换详解(转)

一、建立Flex与Java交互的工程。本文中讲到的交互是利用Blazeds的,因为这个是免费的,呵呵,我是穷人。首先就是去下载Blazeds的压缩包,这个可以从官网或者CSDN、JavaEye上下到。解压缩这个包,将里面的Blazeds.war解压&a…

从行业应用到智慧城市,升哲科技Alpha协议如何保障物理世界的数据传输

随着国家《“十四五”信息通信行业发展规划》和《物联网新型基础设施建设三年行动计划(2021-2023年)》的政策出台,物联网的产业发展迎来了新一波浪潮。在农业、制造业、生态环境、智慧消防等场景下,以数字化转型、智能化升级为动力…

Serverless 工程实践 | 零基础上手 Knative 应用

简介: Knative 是一款基于 Kubernetes 的 Serverless 框架。其目标是制定云原生、跨平台的 Serverless 编排标准。 Knative 介绍 Knative 通过整合容器构建(或者函数)、工作负载管理(动态扩缩)以及事件模型这三者实现…

DataWorks功能实践速览 05——循环与遍历

简介: DataWorks功能实践系列,帮助您解析业务实现过程中的痛点,提高业务功能使用效率!通过往期的介绍,您已经了解到在DataWorks上进行任务运行的最关键的几个知识点,其中上期参数透传中为您介绍了可以将上游…

阿里安全开源顶尖技术“猎豹” 计算更快数据更安全

两家公司想开展合作,发挥各自优势联合开发一款产品,如何以“隐私计算”的形式,在保护隐私的情况下,高效地实现两方联合计算,便成为解决这一问题的关键。 最近,阿里安全最新研发的Cheetah(猎豹&…