無限級的過程mysql
上下級會員關係經過id和pid肯定。sql
例如:a>b>c>d>e>f>g...數組
就是a的下級是b,b的下級是c,c的下級是d....(有點相似傳*銷模式?無視掉)函數
需求,經過用戶g查出全部的上級,則要查到f.e.d.c.b.a這些用戶idthis
方可給這些上級發送通知。設計
咱們最重要的是取出上級id而後就好辦多了。code
首先說明幾個值,user_id 爲用戶表中的用戶id,parent_id爲表中用戶的上級id。字符串
示例一條基本的查詢父級idSQL。get
SELECT parent_id FROM cx_user WHERE user_id = 10;##查詢user_id爲10的上級idstring
不說廢話了,直接進入中心。
打開MySQL開始寫存儲過程。
DROP PROCEDURE IF EXISTS `getpid`; CREATE DEFINER = `root`@`localhost` PROCEDURE `getpid`(IN `id` int) BEGIN SET @pid:=id;#id爲查詢的參數 即當前用戶id SET @pidarr:=','; #查詢到的上級數組字符串 recursion:WHILE @pid!=0 DO SELECT parent_id INTO @pid from cx_users WHERE user_id = @pid;#這裏是你查詢的SQL語句 @pid是動態id IF @pid=0 THEN #到0即結束 LEAVE recursion; END IF; set @substr = concat(",",@pid); set @substr = concat(@substr,','); IF LOCATE(@substr ,@pidarr)>0 THEN #防止出現上下級關係混亂 LEAVE recursion; END IF; set @pidarr = concat(@pidarr,@pid); set @pidarr = concat(@pidarr,','); END WHILE recursion; SELECT @pidarr AS pidarr; END;
存儲過程執行結果,拿圖嚇唬嚇唬你。
PHP端demo
$sql = "CALL getpid(104);"; $pidstr = mysql_query($sql);//換成你項目中執行MySQL的函數便可 而後取出 pidarr的值到$pidstr $pidstr = rtrim($pidstr,',');//剔除最右側多餘英文逗號 $pidstr = ltrim($pidstr,',');//剔除最左側多餘英文逗號 $pidarr = explode(',',$pidstr);//到數組 //如下隨意 #ncSJI$@CO3N#@329090*(@@()$u)@j(@(h(@jn9NCD9823N892
#################### 增長指定層級查詢
首先增長一個字符串查找函數
DROP FUNCTION IF EXISTS `substr_count`; CREATE DEFINER = `root`@`%` FUNCTION `substr_count`(`pstring` varchar(255),`substring` varchar(255)) RETURNS int(11) BEGIN SELECT (LENGTH(pstring) - LENGTH(REPLACE(pstring,substring, ""))) / LENGTH(substring) AS "count" into @ret ; RETURN @ret; END;
修改以前的getpid存儲過程
BEGIN SET @pid:=id; SET @pidarr:=',';/* this return pid */ recursion:WHILE @pid!=0 DO SELECT parent_id INTO @pid from cx_users WHERE user_id = @pid; IF @pid=0 THEN #到0即結束 LEAVE recursion; END IF; set @substr = concat(",",@pid); set @substr = concat(@substr,','); IF LOCATE(@substr,@pidarr)>0 THEN #防止出現上下級關係混亂 LEAVE recursion; END IF; set @pidarr = concat(@pidarr,@pid); set @pidarr = concat(@pidarr,','); #LEVEL 增長的層級判斷 IF substr_count(@pidarr,',')>=level+1 THEN set @pid=0; LEAVE recursion; END IF; END WHILE recursion; SELECT @pidarr AS pidarr; END
調用SQL
CALL getpid(104,2);//獲取用戶id爲104的上級 層級2級 即獲取兩層上級
補充:
在某些MySQL版本中,在某些表的設計中,使用如上過程,出現相似如下報錯。
Result consisted of more than one row
面對這個能夠增長一個臨時交換ID或者是將SQL語句更改下,防止出現返回多個結果行。
SELECT parent_id INTO @pid from cx_users WHERE user_id = @pid LIMIT 1;
今天羣遇到一個網友,使用以上過程,就是查詢不出來數據,結果是NULL,研究好久才發現他的表項設計中出現容許爲NULL的字段,在過程執行中,直接跳過pid=0的判斷,進入concat(",",@pid);的語句,而此時的@pid 是null ,導致合併後的字符串也出現了NULL,更影響告終果@pidarr的數據。
在此,通常只須要將這種關係表設計的更標準些,如NOT NULL DEFAULT '0',或者在過程當中增長額外的判斷NULL、''(EmptyString)的條件讓他跳出WHILE也能夠獲得解決。