sql 没有调试 菜单_MySQL递归查询上下级菜单

正文

在传统的后台管理系统里面经常会需要展示多级菜单关系,今天我们来学一下如何使用一条SQL语句展示多级菜单。

现在我们有一张corpinfo单位表,里面有一个belong字段指向上级单位,首先来看一下现在表里有什么数据:

SELECT uid,ubelong FROM corpinfo

7e17e1f126a5f04bad9912acb4f9eab9.png

现在是类似下面这样的一个三级菜单,uid为1的是我们的顶级菜单,ubelog为0

297e3dc5b2b242925bcf77109040dae8.png

现在我们想实现传入一个 uid ,把当前 uid 和其下级单位的 uid 都展示出来,当然我们可以使用代码或者网上常见的存储过程来实现,但是今天我们用一条SQL语句来实现该效果:

先来看看我们的SQL语句

SELECT DATA.uid FROM(SELECT@ids AS _ids,(SELECT @ids := GROUP_CONCAT(uid)FROM corpinfoWHERE FIND_IN_SET(ubelong, @ids)) AS cids,@l := @l+1 AS levelFROM corpinfo, (SELECT @ids := (参数) , @l := 0 ) bWHERE @ids IS NOT NULL) ID, corpinfo DATA
WHERE FIND_IN_SET(DATA.uid, ID._ids)
ORDER BY level,uid

看下执行结果:

bcb3def39cbbf12ae59354cf73387adf.png

可以看到传入 uid 为 1 后,列出了 uid 为 1 的所有下级单位,连第三级的菜单也列出来了。

57dec0dd8385951b8dc9fc33d2f48cf8.png

比较核心的有下面几个地方:

f2f5c83887e32b78fbda1d3d4068a3bc.png

GROUP_CONCAT()函数

前言:在有 group by 的查询语句中,select指定的字段要么就包含在 group by 语句的后面,作为分组的依据,要么就包含在聚合函数中。

假设我们有一张 user 用户表,我们想查看名字相同的用户的最小年龄,可以这样写:

SELECT name,age FROM user GROUP BY name

执行结果为:

bbf99fa4e732f4929bf2bc5d9594bfe1.png

现在我们想查询 name 相同的用户的所有年龄,当然我们可以这样写:

SELECT name,age FROM user ORDER BY name

执行结果为:

947b9151c6a03109d0debde2b0919b96.png

但是这样同一个名字出现多次,看上去非常不直观。有没有更直观的方法,既让每个名字都只出现一次,又能够显示所有的名字相同的人的id呢?——使用 GROUP_CONCAT() 函数

功能: group by 产生的同一个分组中的值连接起来,返回一个字符串结果。

语法:GROUP_CONCAT( [distinct] 要连接的字段 [ORDER BY 排序字段 ASC/DESC ] [separator '分隔符'] )

SELECT name,GROUP_CONCAT(age) FROM user GROUP BY name

执行结果为:

36c773a2a03e917c111284e822cb796f.png

可以看到相同用户名的年龄都放到一起了,以逗号分割。

FIND_IN_SET函数

假设我们有一张 book 书籍表,有书名和作者两个字段:

SELECT name,author FROM book

执行结果为:

0ed7016c6aee5c92514532cc9d839e56.png

现在我们想查作者包含 小A 的书籍,我们来试一下:

SELECT name,author FROM book WHERE author IN ('小A')

执行结果为:

d72a1f32b9b65021aa5e7fada4727c9c.png

实际上这样是不行的,这样只有当 author 字段的值等于'小A'时(和IN前面的字符串完全匹配),查询才有效,否则都得不到结果。

可能你会想到用LIKE实现,我们来试试看:

SELECT name,author FROM book WHERE author LIKE '%小A%';

执行结果为:

db11ec6f37bf4c7a6927477e0b75f81b.png

可以看到把小AA的书籍也查出来了,所以用LIKE无法实现该功能。

那么我们如何使用 FIND_IN_SET 函数来实现呢?

SELECT name,author FROM book WHERE FIND_IN_SET('小A',author);

执行结果为:

0064c1232c27bdba4416555a74a2d3f6.png

语法:FIND_IN_SET(str,strlist)

str :要查询的字符串strlist :字段名 参数以”,”分隔 如 (1,2,6,8)
查询字段(strlist)中包含(str)的结果,返回结果为null或记录

知道了这两个函数后,现在回过头来看看前面的SQL语句:

77fc08a67b32c4119824054704e572c8.png

运行选中的代码后可以看到列出了上下级的关系,至于细节这里不再展开描述。

既然我们能查出当前单位的所有下级单位,那么应该也能查询所有上级单位,来看下SQL:

SELECT uid FROM(SELECT@id AS _id,( SELECT @id := ubelongFROM corpinfoWHERE uid = @id) AS _pid,@l := @l+1 as levelFROM corpinfo,(SELECT @id := (参数), @l := 0 ) bWHERE @id > 0) ID, corpinfo DATAWHERE ID._id = DATA.uidORDER BY level DESC

还是我们的corpinfo单位表,执行结果为:

40cdafb07d53c21f579566565bc0eab6.png

可以看到当输入 uid 为 5 时,列出了当前单位及其上级所有单位,SQL和上面的差不多,这里不再细说。

最后补充一段代码,既然我们已经拿到想要的单位编号了,接下来就是要递归构建我们的单位树了,来看下代码:

/*** 递归将模块树构建成JSON数组*/
private JSONArray getJsonArray(List<ClCorpinfo> list) {Map<Integer, List<ClCorpinfo>> map = new HashMap<>(16);List<ClCorpinfo> sonList;for (ClCorpinfo clCorpinfo : list) {if (map.get(clCorpinfo.getUbelong()) != null) {sonList = map.get(clCorpinfo.getUbelong());} else {sonList = new ArrayList<>();}sonList.add(clCorpinfo);map.put(clCorpinfo.getUbelong(), sonList);}JSONArray array = new JSONArray();if (list.size() > 0) {array = getChildrenTree(map, 0, 0);}return array;
}
/*** 递归构建模块树的子类*/
public JSONArray getChildrenTree(Map<Integer, List<ClCorpinfo>> map, Integer uparentid, Integer level) {JSONArray array = new JSONArray();for (ClCorpinfo clCorpinfo : map.get(uparentid)) {JSONObject obj = new JSONObject();obj.put("uid", clCorpinfo.getUid());obj.put("ubelong", clCorpinfo.getUbelong());obj.put("ucorpname", clCorpinfo.getUcorpname());obj.put("uparentname", clCorpinfo.getUparentname());if (map.get(clCorpinfo.getUid()) != null) {level++;obj.put("children", getChildrenTree(map, clCorpinfo.getUid(), level));} else {obj.put("children", null);}array.add(obj);}return array;
}

上面这段戴安只要传入单位集合,接下来会递归来构建我们的单位树,接下来只要前端渲染上去就完事了。

总结

其实网上也有很多其它的解决方案,比如用代码实现,也可以用存储过程实现,今天我们使用SQL语句来实现并不一定是最好的办法,虽然简单但是比较难懂,我这边只是给大伙提供一个可行的方案,如果有什么不对的地方请多多指教。

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

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

相关文章

java 桥 word_java导出word的6种方式(转发)

最近做的项目&#xff0c;需要将一些信息导出到word中。在网上找了好多解决方案&#xff0c;现在将这几天的总结分享一下。目前来看&#xff0c;java导出word大致有6种解决方案&#xff1a;1&#xff1a;Jacob是Java-COM Bridge的缩写&#xff0c;它在Java与微软的COM组件之间构…

python删除指定天数前的文件_python 删除指定时间间隔之前的文件实例

遍历指定文件夹下的文件&#xff0c;根据文件后缀名&#xff0c;获取指定类型的文件列表&#xff1b;根据文件列表里的文件路径&#xff0c;逐个获取文件属性里的“修改时间”&#xff0c;如果“修改时间”与“系统当前时间”差值大于某个值&#xff0c;则删除该文件。#!/usr/b…

jieba 词典 词频_在Hanlp词典和jieba词典中手动添加未登录词

在使用Hanlp词典或者jieba词典进行分词的时候&#xff0c;会出现分词不准的情况&#xff0c;原因是内置词典中并没有收录当前这个词&#xff0c;也就是我们所说的未登录词&#xff0c;只要把这个词加入到内置词典中就可以解决类似问题&#xff0c;如何操作呢&#xff0c;下面我…

android访问java服务器_Android_post访问java服务器端

//javaee工程访问地址String url "http://localhost:8080/TestAndroid";//把要请求的值封装到namevalupair的集合中NameValuePair nameValuePair1 new BasicNameValuePair("name","zhangsna");NameValuePair nameValuePair2 new BasicNameVal…

pythonweb啥意思_python-web-guide

Python Web 入坑指南____ _ _ __ __ _ ____ _ _| _ \ _ _| |_| |__ ___ _ __ \ \ / /__| |__ / ___|_ _(_) __| | ___| |_) | | | | __| _ \ / _ \| _ \ \ \ /\ / / _ \ _ \ | | _| | | | |/ _ |/ _ \| __/| |_| | |_| | | | (_) | | | | \ V V / __/ |_) | | |_| | |_| | | (_…

java范例_Java范例集锦(一)

范例1&#xff1a;不用其他变量实现两个变量通常在对变量互换时&#xff0c;将创建一个临时变量来共同完成互换&#xff0c;临时变量的互换增加了系统资源的消耗。如果需要交换的是两个整数类型的变量&#xff0c;则可以使用异或运算符(^)进行更高效的处理。实现代码如下&#…

python查找输出文字_Python基础练习,查询文本内容并输出;

1、编写可供用户查询的员工信息表&#xff1a;1).用户认证(输入用户名&#xff0c;密码)2).查询关键字&#xff1a;姓名3).显示ID&#xff0c;name&#xff0c;section&#xff0c;phone4).员工信息表内容如下&#xff1a;cat search_name.txt001wenlong IT12345678002xiaojun …

python列表索引超出范围 等于啥_python - IndexError:列表分配索引超出范围,Python

我正在尝试实现功能。它的工作方式应该是这样的&#xff1a;它需要两个列表。标记一些索引&#xff0c;最好居中。父母双方都切换标记索引。其他索引按顺序转到其父元素。如果该父元素中已经存在相同的元素&#xff0c;则它将映射并检查同一元素在其他父元素的位置并到达那里。…

python爬取汽车之家_python爬取 汽车之家(汽车授权经销商)

一&#xff1a;爬虫的目标&#xff1a;打开汽车之家的链接&#xff1a;https://www.autohome.com.cn/beijing/&#xff0c;出现如下页面我们的目标是点击找车&#xff0c;然后出现如下图我们要把图中的信息抓取到二&#xff1a;实现过程我们选择 宝马5系 然后点击找车注意宝马…

python跨目录调用_python 跨目录访问文件

1.同级、同目录的文件之间的访问有这样一个目录结构假如&#xff0c;in_A.py 这个文件想调用 hello_world.py 中的函数怎么办呢&#xff1f; --->>> import只需在 in_A.py 中 写入importhello_worldhello_world.functions()这样就可以访问啦&#xff0c;什么原理呢&a…

Java 调用 Caffe_解决 free(): invalid pointer: 0x00000000019ff700 运行时报错(caffe)(libtool使用)...

编译成功&#xff0c;运行时报错&#xff1a;在使用 pytorch or tensorflow or caffe 时&#xff0c;都可能存在这个问题&#xff1a;*** Error in xxx: free(): invalid pointer: 0x00000000020663b0 ***很可能是缺少libtcmalloc库解决方法1&#xff1a;apt-get安装libtcmallo…

unity 世界坐标间角度_Unity学习笔记—本地坐标转世界坐标

核心用到的方法就是transform.TransformPoint( )这个方法的返回值就是Vector3类型的世界坐标&#xff0c;transform就是相对的物体&#xff0c;括号里的就是相对这个transform的本地坐标&#xff0c;比方说我现在的位置吧&#xff0c;知道我相对于我的邻居的坐标:Pos1&#xff…

python访问序列元素的编号用什么括起来_python-重新编号数组中元素的有效方法...

我是python的新手,正在尝试实现一种遗传算法,但需要其中一项操作的代码方面的帮助.我是这样提出问题的&#xff1a;>每个人我都由一串M个整数表示> I中的每个元素e取值从0到N> 0到N之间的每个数字都必须在I中至少出现一次> e的值并不重要,只要每个唯一值元素采用相…

java 下载代码_实现文件下载的java代码

实现文件下载的java代码//这是实现下载类(servlet)&#xff0c;详细思路代码例如以下&#xff1a;//也可连接数据库package com.message;import javax.servlet.*;import javax.servlet.http.*;import java.io.*;import java.util.*;public class FileDownServlet extends HttpS…

webcomponents安装了没有用_Web Components 入门实例教程

来源 | http://www.ruanyifeng.com/blog/2019/08/web_components.html组件是前端的发展方向&#xff0c;现在流行的React和Vue都是组件框架。谷歌公司由于掌握了Chrome浏览器&#xff0c;一直在推动浏览器的原生组件&#xff0c;即Web组件API。部分第三方框架&#xff0c;原生组…

虹软java接摄像头_虹软人脸识别SDK(java+linux/window) 初试

虹软人脸识别全平台demo调用—快速上手之服务端Windows篇demo名称&#xff1a;ArcFace 2.2 Windows(86) Demo [C]一 环境配置&#xff1a;1) 安装VS2013环境安装包(vcredist_x86_vs2013.exe)2) 从官网(http://www.arcsoft.com.cn/ai/arcface.html)申请sdk&#xff0c;下载对应的…

python中re_Python中re(正则表达式)模块学习

今天学习了Python中有关正则表达式的知识。关于正则表达式的语法&#xff0c;不作过多解释&#xff0c;网上有许多学习的资料。这里主要介绍Python中常用的正则表达式处理函数。re.matchre.match 尝试从字符串的开始匹配一个模式&#xff0c;如&#xff1a;下面的例子匹配第一个…

java ee 上传文件_17.《JavaEE 学习笔记》Servlet 上传文件

功能介绍&#xff1a;利用 Servlet 和表单提交&#xff0c;选择本地文件上传到服务器。上传的文件可以是文本文件或图像文件或任何文档&#xff0c;不能是文件夹。需要引入的 jar 文件&#xff1a;commons-fileupload-1.3.2、commons-io-2.5.jar。下载链接&#xff1a;将下载好…

spark python 上传代码包_使用 Livy Rest API 提交 spark 批量任务 (jar,Python, streaming)...

Livy是一个开源的REST 接口&#xff0c;用于与Spark进行交互&#xff0c;它同时支持提交执行代码段和完整的程序。image.pngLivy封装了spark-submit并支持远端执行。启动服务器执行以下命令&#xff0c;启动livy服务器。./bin/livy-server这里假设spark使用yarn模式&#xff0c…

java中可以改变引用的指向吗_java中引用传递问题,在函数中修改引用的指向,会不会影响实参?...

大家讲道理2017-04-17 15:30:345楼是时候展现一下我的JAVA基础知识了&#xff0c;2333。我按照执行顺序给你写注释好了。Person p1 new Person(10);//创建了一个对象//p1.age10;modify(p1);//modify函数传参&#xff0c;创建了一个在modify函数里面的局部变量p//你应该明白p是…