最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Mysql 實(shí)現(xiàn)向上遞歸查找父節(jié)點(diǎn)并返回樹(shù)結(jié)構(gòu)的示例代碼

 更新時(shí)間:2022年09月11日 15:11:24   作者:HiEagle  
通過(guò)mysql 8.0以下版本實(shí)現(xiàn),一個(gè)人多角色id,一個(gè)角色對(duì)應(yīng)某個(gè)節(jié)點(diǎn)menu_id,根節(jié)點(diǎn)的父節(jié)點(diǎn)存儲(chǔ)為NULL, 向上遞歸查找父節(jié)點(diǎn)并返回樹(shù)結(jié)構(gòu),今天通過(guò)本文給大家介紹Mysql遞歸查找父節(jié)點(diǎn)并返回樹(shù)結(jié)構(gòu),感興趣的朋友一起看看吧

通過(guò)mysql 8.0以下版本實(shí)現(xiàn),一個(gè)人多角色id,一個(gè)角色對(duì)應(yīng)某個(gè)節(jié)點(diǎn)menu_id,根節(jié)點(diǎn)的父節(jié)點(diǎn)存儲(chǔ)為NULL, 向上遞歸查找父節(jié)點(diǎn)并返回樹(shù)結(jié)構(gòu)。如果只有葉子,剔除掉; 如果只有根,只顯示一個(gè)禿頂?shù)母?;如果既有葉子又有根則顯示葉子與根。如果 傳入角色I(xiàn)D 5,15,25,26,則只查找5,15的所有父節(jié)點(diǎn),因?yàn)?5,26無(wú)根節(jié)點(diǎn)

需求:通過(guò)mysql 8.0以下版本實(shí)現(xiàn),一個(gè)人多角色id,一個(gè)角色對(duì)應(yīng)某個(gè)節(jié)點(diǎn)menu_id,根節(jié)點(diǎn)的父節(jié)點(diǎn)存儲(chǔ)為NULL, 向上遞歸查找父節(jié)點(diǎn)并返回樹(shù)結(jié)構(gòu)。

如果只有葉子,剔除掉; 如果只有根,只顯示一個(gè)禿頂?shù)母?;如果既有葉子又有根則顯示葉子與根。測(cè)試數(shù)據(jù):

如果 傳入角色I(xiàn)D【auth_id】: 5,15,25,26,則只查找5,15的所有父節(jié)點(diǎn),因?yàn)?5,26無(wú)根節(jié)點(diǎn)

測(cè)試數(shù)據(jù):

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for Menu
-- ----------------------------
DROP TABLE IF EXISTS `Menu`;
CREATE TABLE `Menu` (
  `menu_id` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '0',
  `sup_menu` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
  `auth_id` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
  PRIMARY KEY (`menu_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
 
-- ----------------------------
-- Records of Menu
-- ----------------------------
BEGIN;
INSERT INTO `Menu` VALUES ('1', NULL, '1');
INSERT INTO `Menu` VALUES ('11', NULL, '11');
INSERT INTO `Menu` VALUES ('12', '11', '12');
INSERT INTO `Menu` VALUES ('13', '11', '13');
INSERT INTO `Menu` VALUES ('14', '12', '14');
INSERT INTO `Menu` VALUES ('15', '12', '15');
INSERT INTO `Menu` VALUES ('16', '13', '16');
INSERT INTO `Menu` VALUES ('17', '13', '17');
INSERT INTO `Menu` VALUES ('2', '1', '2');
INSERT INTO `Menu` VALUES ('22', '21', '26');
INSERT INTO `Menu` VALUES ('25', '22', '25');
INSERT INTO `Menu` VALUES ('3', '1', '3');
INSERT INTO `Menu` VALUES ('4', '2', '4');
INSERT INTO `Menu` VALUES ('5', '2', '5');
INSERT INTO `Menu` VALUES ('6', '3', '6');
INSERT INTO `Menu` VALUES ('7', '3', '7');
COMMIT;
 
SET FOREIGN_KEY_CHECKS = 1;

 方法一:純存儲(chǔ)過(guò)程實(shí)現(xiàn)

-- 純存儲(chǔ)過(guò)程實(shí)現(xiàn)
DELIMITER //
-- 如果只有葉子,剔除掉; 如果只有根,只顯示一個(gè)禿頂?shù)母?;如果既有葉子又有根則顯示
DROP PROCEDURE if EXISTS  query_menu_by_authid;
CREATE PROCEDURE query_menu_by_authid(IN roleIds varchar(1000))

BEGIN
-- 用于判斷是否結(jié)束循環(huán)
declare done int default 0;
-- 用于存儲(chǔ)結(jié)果集
declare menuid bigint;
declare temp_menu_ids VARCHAR(3000);
declare temp_sup_menus VARCHAR(3000);
declare return_menu_ids VARCHAR(3000);

-- 定義游標(biāo)
declare idCur cursor for select menu_id from Menu where  FIND_IN_SET(auth_id,roleIds) ;
-- 定義 設(shè)置循環(huán)結(jié)束標(biāo)識(shí)done值怎么改變 的邏輯
declare continue handler for not FOUND set done = 1;


open idCur ;
FETCH idCur INTO menuid;
-- 臨時(shí)變量存儲(chǔ)menu_id集合
SET temp_menu_ids = '';
-- 返回存儲(chǔ)menu_id集合
SET return_menu_ids = '';

WHILE done<> 1 DO
--  只查找 單個(gè) auth_id  相關(guān)的menu_id
-- 通過(guò)authid, 查找出menu_id, sup_menu is null

SELECT
GROUP_CONCAT(T2._menu_id) as t_menu_id,
GROUP_CONCAT(T2._sup_menu) as t_sup_menu
into temp_menu_ids,temp_sup_menus
FROM
     (
       SELECT
       -- 保存當(dāng)前節(jié)點(diǎn)。(從葉節(jié)點(diǎn)往根節(jié)點(diǎn)找,@r 保存當(dāng)前到哪個(gè)位置了)。@r 初始為要找的節(jié)點(diǎn)。
       -- _menu_id 當(dāng)前節(jié)點(diǎn)
       DISTINCT @r as _menu_id,
             (
           SELECT
             CASE
                        WHEN sup_menu IS NULL THEN @r:= 'NULL'
                        ELSE @r:= sup_menu
             END
             FROM Menu
             WHERE  _menu_id = Menu.menu_id
             ) AS _sup_menu,
       -- 保存當(dāng)前的Level
       @l := @l + 1 AS level
       FROM
       ( SELECT @r := menuid, @l := 0
       ) vars, Menu AS temp
        -- 如果該節(jié)點(diǎn)沒(méi)有父節(jié)點(diǎn),則會(huì)被置為0
        WHERE  @r <> 0
        ORDER BY @l DESC
       ) T2
      INNER JOIN Menu T1
    ON T2._menu_id = T1.menu_id
 ORDER BY T2.level DESC ;

 -- 滿足必須要有根節(jié)點(diǎn)NULL字符,則表明有根,否則不拼接給返回值
 IF FIND_IN_SET('NULL',temp_sup_menus) > 0  THEN
 SET return_menu_ids = CONCAT(temp_menu_ids,',',return_menu_ids);
 END IF;

FETCH idCur INTO menuid;
END WHILE;
CLOSE  idCur;

-- 返回指定menu_id 的數(shù)據(jù)集合
select Menu.menu_id,Menu.sup_menu,Menu.auth_id
FROM Menu
WHERE FIND_IN_SET(menu_id,return_menu_ids)
ORDER BY Menu.menu_id*1 ASC ;

END;
//
DELIMITER;

CALL  query_menu_by_authid('5,15,25,26');
CALL  query_menu_by_authid('5,17');
CALL  query_menu_by_authid('5,11');

方法二:函數(shù)+存儲(chǔ)過(guò)程實(shí)現(xiàn)

-- 函數(shù)+存儲(chǔ)過(guò)程實(shí)現(xiàn)
-- 根據(jù)葉子節(jié)點(diǎn)查找所有父節(jié)點(diǎn)及其本身節(jié)點(diǎn)。如果只有葉子,剔除掉; 如果只有根,只顯示一個(gè)禿頂?shù)母?;如果既有葉子又有根則顯示.
DROP FUNCTION  IF EXISTS `getParentList`;
CREATE FUNCTION `getParentList`(in_menu_id varchar(255))
RETURNS varchar(3000)
BEGIN
    DECLARE sTemp VARCHAR(3000);
    DECLARE sTempPar VARCHAR(3000);
    SET sTemp = '';
    SET sTempPar = in_menu_id;

    -- 循環(huán)遞歸
    WHILE sTempPar is not null DO
        -- 判斷是否是第一個(gè),不加的話第一個(gè)會(huì)為空
        IF sTemp != '' THEN
            SET sTemp = concat(sTemp,',',sTempPar);
        ELSE
            SET sTemp = sTempPar;
        END IF;
        SET sTemp = concat(sTemp,',',sTempPar);
        SELECT group_concat(sup_menu)
                INTO sTempPar
                FROM Menu
                where sup_menu<>menu_id
                and FIND_IN_SET(menu_id,sTempPar) > 0;
    END WHILE;
    RETURN sTemp;
END;


DELIMITER //
-- 如果只有葉子,剔除掉; 如果只有根,只顯示一個(gè)禿頂?shù)母?;如果既有葉子又有根則顯示
DROP PROCEDURE if EXISTS  select_menu_by_authids ;
CREATE PROCEDURE select_menu_by_authids(IN roleIds varchar(3000))

BEGIN
-- 用于判斷是否結(jié)束循環(huán)
declare done int default 0;
-- 用于存儲(chǔ)結(jié)果集
declare menuid varchar(255);
declare set_menu_ids VARCHAR(3000);
--  檢查是否單葉子節(jié)點(diǎn) 單葉子節(jié)點(diǎn) sup_menu is not null
-- sup_menu 是否為null
declare _sup_menu int default -1;

-- 定義游標(biāo)
declare idCur cursor for select menu_id from Menu where  FIND_IN_SET(auth_id,roleIds) ;
-- 定義 設(shè)置循環(huán)結(jié)束標(biāo)識(shí)done值怎么改變 的邏輯
declare continue handler for not FOUND set done = 1;

OPEN idCur ;
FETCH idCur INTO menuid;
-- 臨時(shí)變量存儲(chǔ)menu_id集合
SET set_menu_ids = '';

WHILE done<> 1 DO
SELECT  sup_menu
INTO _sup_menu
FROM Menu
WHERE FIND_IN_SET(menu_id,getParentList(menuid))
ORDER BY sup_menu ASC
LIMIT 1;

-- 查找指定角色對(duì)應(yīng)的menu_id ,sup_menu is null 則說(shuō)明有根,則進(jìn)行拼接
IF _sup_menu is NULL THEN
SELECT  CONCAT(set_menu_ids, GROUP_CONCAT(menu_id),',') INTO set_menu_ids
FROM Menu
where FIND_IN_SET(menu_id,getParentList(menuid)) ;
END IF;

FETCH idCur INTO menuid;
END WHILE;
CLOSE  idCur;

-- 返回指定menu_id 的數(shù)據(jù)集合
SELECT Menu.menu_id,Menu.sup_menu,Menu.auth_id
FROM Menu
WHERE FIND_IN_SET(menu_id,set_menu_ids)
ORDER BY Menu.menu_id*1 ASC  ;

END ;
//
DELIMITER ;

CALL  select_menu_by_authids('5,15,25,26');
CALL  select_menu_by_authids('5,17');
CALL  select_menu_by_authids('5,11');

方法三:純函數(shù)實(shí)現(xiàn)

-- 根據(jù)葉子節(jié)點(diǎn)查找所有父節(jié)點(diǎn)及其本身節(jié)點(diǎn)。如果只有葉子,剔除掉; 如果只有根,只顯示一個(gè)禿頂?shù)母?;如果既有葉子又有根則顯示.
DROP FUNCTION  IF EXISTS `getParentLists`;
-- 參數(shù)1角色id 字符串逗號(hào)隔開(kāi); 參數(shù)2 角色id 個(gè)數(shù)
CREATE FUNCTION `getParentLists`(in_roleIds varchar(1000),count_roleIds INT)
RETURNS VARCHAR(3000)
BEGIN
    -- 臨時(shí)存放通過(guò)單個(gè)角色查找的單個(gè)menu_id
        DECLARE sMenu_id_by_roleId VARCHAR(1000);
    -- 臨時(shí)存放通過(guò)單個(gè)角色查找的多個(gè)menu_id
    DECLARE sMenu_ids_by_roleId VARCHAR(1000);
        -- 臨時(shí)存放通過(guò)多個(gè)角色查找的多個(gè)menu_id
    DECLARE sMenu_ids_by_roleIds VARCHAR(1000);
        -- 函數(shù)返回的menu_id 集合
        DECLARE sReturn_menu_ids VARCHAR(3000);
        -- 當(dāng)前角色
    DECLARE current_roleId_rows INT DEFAULT 0;

        SET sMenu_id_by_roleId = '';
    SET sMenu_ids_by_roleIds = '';
        SET sReturn_menu_ids = '';

         -- 循環(huán)多角色
        WHILE current_roleId_rows < count_roleIds DO

                -- 依次按角色取1條menu_id
                SELECT menu_id
                INTO sMenu_id_by_roleId
                FROM Menu
                WHERE FIND_IN_SET(auth_id, in_roleIds)
                ORDER BY menu_id DESC
                LIMIT current_roleId_rows, 1 ;

                SET sMenu_ids_by_roleId = sMenu_id_by_roleId;
        WHILE sMenu_ids_by_roleId IS NOT NULL DO

                        -- 判斷是否是第一個(gè),不加的話第一個(gè)會(huì)為空
                        IF sMenu_ids_by_roleIds != ''  THEN
                                SET sMenu_ids_by_roleIds = CONCAT(sMenu_ids_by_roleIds,',',sMenu_ids_by_roleId);
                        ELSE
                                SET sMenu_ids_by_roleIds = sMenu_ids_by_roleId;
                        END IF;

                        -- 通過(guò)角色id 拼接 所有的父節(jié)點(diǎn),重點(diǎn)拼接根節(jié)點(diǎn),根節(jié)點(diǎn)置為字符NULL,用于后面判斷是否有根
                        SELECT
                        GROUP_CONCAT(
                        CASE
                        WHEN sup_menu IS NULL THEN  'NULL'
                        ELSE sup_menu
                        END
                        )
                        INTO sMenu_ids_by_roleId
                        FROM Menu
                        WHERE FIND_IN_SET(menu_id,sMenu_ids_by_roleId) > 0;

       END WHILE;
             SET current_roleId_rows=current_roleId_rows+1;

             -- 滿足必須要有根節(jié)點(diǎn)NULL字符,則表明有根,否則不拼接給返回值
             IF  FIND_IN_SET('NULL',sMenu_ids_by_roleIds) > 0 THEN
                         SET sReturn_menu_ids = CONCAT(sReturn_menu_ids,',',sMenu_ids_by_roleIds);
             END IF;

             -- 清空通過(guò)單個(gè)角色查到的多個(gè)menu_id, 避免重復(fù)拼接
             SET sMenu_ids_by_roleIds = '';
   END WHILE;

   RETURN sReturn_menu_ids;
END;

SELECT Menu.menu_id,Menu.sup_menu,Menu.auth_id
FROM Menu
WHERE FIND_IN_SET(menu_id, getParentLists('15,25,5,26',4))
ORDER BY Menu.menu_id+0 ASC;

SELECT Menu.menu_id,Menu.sup_menu,Menu.auth_id
FROM Menu
WHERE FIND_IN_SET(menu_id, getParentLists('17,5',2))
ORDER BY Menu.menu_id*1 ASC;

SELECT Menu.menu_id,Menu.sup_menu,Menu.auth_id
FROM Menu
WHERE FIND_IN_SET(menu_id, getParentLists('11,5',2))
ORDER BY Menu.menu_id*2 ASC;

到此這篇關(guān)于Mysql 實(shí)現(xiàn) 向上遞歸查找父節(jié)點(diǎn)并返回樹(shù)結(jié)構(gòu)的文章就介紹到這了,更多相關(guān)Mysql遞歸查找父節(jié)點(diǎn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL8.0實(shí)現(xiàn)窗口函數(shù)計(jì)算同比環(huán)比

    MySQL8.0實(shí)現(xiàn)窗口函數(shù)計(jì)算同比環(huán)比

    本文主要介紹了MySQL8.0實(shí)現(xiàn)窗口函數(shù)計(jì)算同比環(huán)比,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • linux下啟動(dòng)或者關(guān)閉MySQL數(shù)據(jù)庫(kù)的多種方式

    linux下啟動(dòng)或者關(guān)閉MySQL數(shù)據(jù)庫(kù)的多種方式

    ,在Linux服務(wù)器上管理MySQL服務(wù)是一個(gè)基本的運(yùn)維任務(wù),下面這篇文章主要給大家介紹了關(guān)于linux下啟動(dòng)或者關(guān)閉MySQL數(shù)據(jù)庫(kù)的多種方式,文中通過(guò)代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • mysql報(bào)錯(cuò)1033 Incorrect information in file: ‘xxx.frm’問(wèn)題的解決方法

    mysql報(bào)錯(cuò)1033 Incorrect information in file: ‘xxx.frm’問(wèn)題的解決方法

    這篇文章主要介紹了關(guān)于mysql報(bào)錯(cuò)1033 Incorrect information in file: 'xxx.frm'問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的很詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-03-03
  • Mysql默認(rèn)設(shè)置的危險(xiǎn)性分析

    Mysql默認(rèn)設(shè)置的危險(xiǎn)性分析

    一.mysql默認(rèn)的授權(quán)表二.缺乏日志能力 三.my.ini文件泄露口令 四.服務(wù)默認(rèn)被綁定全部的網(wǎng)絡(luò)接口上 五.默認(rèn)安裝路徑下的mysql目錄權(quán)限
    2008-09-09
  • MySQL多列IN查詢的實(shí)現(xiàn)

    MySQL多列IN查詢的實(shí)現(xiàn)

    多列 IN 查詢是一種強(qiáng)大的篩選工具,它允許通過(guò)多字段組合快速過(guò)濾數(shù)據(jù),本文主要介紹了MySQL 多列 IN 查詢的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • MySQL 5.5.49 大內(nèi)存優(yōu)化配置文件優(yōu)化詳解

    MySQL 5.5.49 大內(nèi)存優(yōu)化配置文件優(yōu)化詳解

    最近mysql服務(wù)器升級(jí)到了MySQL 5.5.49版本,性能比mysql 5.0.**肯定效率高了不少,但mysql的默認(rèn)配置文件不合理,這里是針對(duì)大內(nèi)存訪問(wèn)量大的機(jī)器的配置方案,需要的朋友可以參考下
    2016-05-05
  • Mysql數(shù)據(jù)庫(kù)group?by原理詳解

    Mysql數(shù)據(jù)庫(kù)group?by原理詳解

    這篇文章主要為大家介紹了Mysql數(shù)據(jù)庫(kù)group?by的原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • MySQL之Innodb_buffer_pool_size設(shè)置方式

    MySQL之Innodb_buffer_pool_size設(shè)置方式

    這篇文章主要介紹了MySQL之Innodb_buffer_pool_size設(shè)置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • sql與各個(gè)nosql數(shù)據(jù)庫(kù)使用場(chǎng)景的講解

    sql與各個(gè)nosql數(shù)據(jù)庫(kù)使用場(chǎng)景的講解

    今天小編就為大家分享一篇關(guān)于sql與各個(gè)nosql數(shù)據(jù)庫(kù)使用場(chǎng)景的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-03-03
  • hive從mysql導(dǎo)入數(shù)據(jù)量變多的解決方案

    hive從mysql導(dǎo)入數(shù)據(jù)量變多的解決方案

    這篇文章主要介紹了hive從mysql導(dǎo)入數(shù)據(jù)量變多的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01

最新評(píng)論

贵溪市| 张家口市| 盐池县| 资溪县| 扎鲁特旗| 新营市| 东乡县| 加查县| 民县| 旬邑县| 颍上县| 潜江市| 昭苏县| 玉山县| 静海县| 永和县| 慈溪市| 阳新县| 沙洋县| 开封市| 汉寿县| 德保县| 大邑县| 益阳市| 马鞍山市| 桂东县| 宁海县| 锡林郭勒盟| 泸水县| 泸州市| 武宣县| 伊川县| 大庆市| 化德县| 镇雄县| 叙永县| 栾川县| 滦南县| 陇西县| 云梦县| 大安市|