首页 > 数据库 >mysql用户变量的应用:查询所有的节点或查询所有的子节点

mysql用户变量的应用:查询所有的节点或查询所有的子节点

时间:2022-10-14 17:45:41浏览次数:52  
标签:parent 节点 mysql org pids 查询 id SELECT

用户变量:以"@"开始,形式为"@变量名"

创建用户定义的变量,请使用格式@variable_name,其中variable_name包含字母数字字符。从MySQL 5.7.5开始,用户定义变量的最大长度为64个字符

用户定义的变量不区分大小写。这意味着@id和@ID是一样的

局部变量与用户变量的区别:

1、用户变量是以"@"开头的。局部变量没有这个符号;

2、定义变量不同。用户变量使用set语句,局部变量使用declare语句定义;

3、作用范围。局部变量只在begin-end语句块之间有效。在begin-end语句块运行完之后,局部变量就消失了。

一、用户变量赋值

1、使用set进行赋值,此时可以用:=或=

语法:

SET @variable_name := value;
# or
SET @variable_name = value;

没有指定GLOBAL 或SESSION,那么默认将会定义用户变量。

example:

SET @num = 2;
SELECT @num as test;

结果:

2、select语句中赋值,必须使用 := 赋值运算符,因为在SELECT语句中,MySQL将=运算符视为等于运算符

语法:

SELECT @variable_name := value; 

example:

赋值之后,可以在允许表达式的后续语句中使用变量,例如,在WHERE子句,INSERT或UPDATE语句

举例

先创建一个logs表,如下所示:

1、获取表中最大的num并赋值@max

SELECT @max := MAX(num) FROM `logs`

结果:

2、根据@max筛选数据,@max 存储在临时表,关联查找最大值对应的行数据

select id,num from logs,(SELECT @max := MAX(num) FROM `logs`) t where num=@max

结果:

3、用户定义的变量只能包含单个值。如果SELECT语句返回多个值,则变量将采用结果中最后一行的值。

select @max := num from logs where num > 0

结果:

此时select @max as test

我们给logs表再增加一行数据来验证:

说明如果SELECT语句返回多个值,则变量将采用结果中最后一行的值。

用户变量在mysql客户端退出后,会自动消失,之后我打开客户端,使用"select @max;" 显示变了的值为null,说明,未定义的变量初始化是null.

我们先给@max赋值为5

关闭navicat后再次打开,执行select @max as test,结果为null。

二、用户变量的应用

先创建表t_user,如下所示:

通过自连接,形成一个树状结构

问:如何查询子节点所有的父节点,例如,如何查询5上面所有的父节点。

SELECT
@r AS _id,
(SELECT @r := parent_id FROM t_user WHERE t_id = _id) AS parent_id,
@l := @l + 1 AS lvl FROM (SELECT @r := 5, @l := 0) vars,
t_user h WHERE @r <> 0

@r表示声明了一个用户变量r,@r :保存当前节点。(从叶节点往根节点找,@r 保存当前到哪个位置了)。@r 初始为要找的节点。即 @r := 5

_id:当前节点。@r <> 0 表示_id!=0,因为_id等于0是不合理的

结果如下:

lvl表示level,即:1=自身,2=父节点,3=父节点的父节点,以此类推。如果不需要,可以去掉。

如上图所示,只需要修改我标注的两个地方即可(当然,表明和字段名也要做响应修改):

  • 5:要查询的子节点
  • 0: 如果该节点没有父节点(即是顶节点),则会被置位 0

下面开始拆解SQL:

(1)、首先初始化变量@r和@l。即(SELECT @r := 5, @l := 0) vars
(2)、@r AS _id 将当前节点作为查询结果 _id
(3)、查找当前节点_id的父节点,将其赋给@r,然后作为查询结parent_id。即 (SELECT @r := parent_id FROM t_user WHERE t_id = _id) AS parent_id
(4)、将@l加1,并作为查询结果lvl。即 @l := @l + 1 AS lvl
  循环 2,3,4 步骤,得到如下结果:

去掉where条件就是上图的执行结果

(5)、执行where条件,过滤掉 @r <> 0 (_id!=0),

SELECT
@r AS _id,
(SELECT @r := parent_id FROM t_user WHERE t_id = _id) AS parent_id,
@l := @l + 1 AS lvl FROM (SELECT @r := 5, @l := 0) vars,
t_user h WHERE   @r <> 0 

结果如下:

三、查询所有的父节点(包含自己)

<select id="selectTreeParentByNo" resultMap="resultMap">
        SELECT T2.* FROM (
          SELECT
          @R AS _id,
          ( SELECT @R := parent_no FROM t_org WHERE org_no = _id ) AS PARENT_ID,
          @L := @L + 1 AS LVL
          FROM
          (SELECT @R := #{orgNo}, @L := 0) VARS, t_org h
          WHERE @R <![CDATA[>=]]> 0
        ) T1 INNER JOIN t_org T2 ON T1._id = T2.org_no
        ORDER BY T1.LVL DESC;
    </select>

四、查询所有的父节点(不包含自己)

<select id="selectTreeParentByNo" resultMap="resultMap">
        SELECT T2.* FROM (
        SELECT
        @R AS _id,
        ( SELECT @R := PARENT_no FROM t_org WHERE org_no = _id ) AS PARENT_ID,
        @L := @L + 1 AS LVL
        FROM
        (SELECT @R := #{orgNo}, @L := 0) VARS, t_org h
        WHERE @R <![CDATA[>=]]> 0
        ) T1 INNER JOIN t_org T2 ON T1._id = T2.org_no AND T2.org_no != #{orgNo}
        ORDER BY T1.LVL DESC;
    </select>

五、查询当前节点的所有的子节点(包含自己)

    select t3.* from (
              select t1.*,
                   if(find_in_set(parent_id, @pids) > 0, @pids := concat(@pids, ',', id), if (t1.id = #{orgNo},#{orgNo},0)) as ischild
               from (
                     select org_no as id, parent_no as parent_id,org_name as orgName,t.* from t_org t
                ) t1,
                (select @pids :=  #{orgNo}) t2
        ) t3 where ischild <![CDATA[<>]]> '0'
    </select>

if函数:IF(expr1,expr2,expr3) :如果expr1是TRUE(expr1<>0且expr1<>NULL),那么IF()返回expr2,否则它返回expr3。

下面开始拆解SQL:

(1)、首先初始化变量@pids,将当前部门的orgNo赋值给@pids。即(select @pids := #{orgNo}) t2

(2)、查询t_org表的所有记录,将t_org表的org_no赋值给id,parent_no赋值给parent_id,org_name赋值给orgName。即(select org_no as id, parent_no as parent_id,org_name as orgName,t.* from t_org t) t

(3)、如果parent_id在@pids中,该部门为当前节点的子部门,即find_in_set(parent_id, @pids) > 0为true,则将该部门的id拼接到@pids后面,逗号相隔。如果该部门不是当前节点的子部门,但是该部门的id即为当前节点的orgNo,即该部门为当前部门,则if(find_in_set(parent_id, @pids) > 0, @pids := concat(@pids, ',', id), if (t1.id = #{orgNo},#{orgNo},0))的值为当前节点的orgNo;如果该部门不是当前节点的子部门,也不是当前节点,则通过where后面的条件(ischild != 0)去除。

六、查询当前节点的所有的子节点(不包含自己)

    select t3.* from (
              select t1.*,
                   if(find_in_set(parent_id, @pids) > 0, @pids := concat(@pids, ',', id), 0) as ischild
               from (
                     select org_no as id, parent_no as parent_id,org_name as orgName,t.* from t_org t
                ) t1,
                (select @pids :=  #{orgNo}) t2
        ) t3 where ischild <![CDATA[<>]]> '0'
    </select>

 

标签:parent,节点,mysql,org,pids,查询,id,SELECT
From: https://www.cnblogs.com/zwh0910/p/16791555.html

相关文章

  • 项目概述、部署数据库服务mysql、配置网站服务、测试配置
    Project3_day01知识点:一、准备数据库服务器二、搭建数据库服务器三、配置MySQL主从同步四、配置读写分离服务器五、配置数据库服务器六、配置网站服务器七、测试配......
  • 数据库第九次作业-连接查询&子查询
    目录​​1.查询“Chisel”所在车间的车间编号、车间主任姓名、主任联系方式​​​​2.查询所有员工姓名、员工联系电话、车间地址、车间主任姓名、主任联系方式​​​​3.查......
  • 数据库第五次作业-查询数据
    目录​​1.查询教师表中教师号在T5到T10之间的所有字段数据​​​​2.查询授课表中周数为14的课程号、教师号、周数、教室号字段数据​​​​ 3.查询授课表中去重后的......
  • 项目4 MySQL数据表的检索总结
    目录​​【任务4.1】查询时选择列​​​​1.基本查询语句​​​​2,检索所有列​​​​3.检索指定列​​​​(1)检索单个字段​​​​(2)检索多个字段​​​​(3)定义别名​​​......
  • navicat 如何调整查询区域字体大小
    Navicat是一套快速、可靠和全面的数据库管理工具,专门用于简化数据库管理和降低管理成本。Navicat图形界面直观,提供简便的管理方法,设计和操作MySQL、MariaDB、SQLServer、O......
  • MySQL全局锁和表锁
    MySQL全局锁和表锁该文摘抄自林晓斌老师的文章数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁......
  • 数据库内置表的研究 & Mysql的文件操作
    数据库内置表的研究+通过命令写shell0x00SQLite内置表的研究SQLITE_MASTER表是一张SQLite数据库的伴生表,该表会自动创建,是用来存储数据库的元信息的,如:表(table),索引......
  • MySql的CURRENT_TIMESTAMP
    MySql的CURRENT_TIMESTAMP在创建时间字段的时候DEFAULTCURRENT_TIMESTAMP表示当插入数据的时候,该字段默认值为当前时间ONUPDATECURRENT_TIMESTAMP表示每次更新这条数......
  • Mysql基础第二天,安装Navicat
    1.我们到http://www.navicat.com这个网站下载Navicat2.现在开始安装3.点击下一步之后4.点击下一步5.点击下一步,等待安装6.点击完成7.打开软件,我们新建一个连接8.点击Mysql......
  • Mysql基础第十天,数据过滤
    1.组合WHERE子句selectprod_name,vend_id,prod_pricefromproductswherevend_id=1003andprod_price=2.5;//使用andselectprod_name,vend_id,prod_pricefrompr......