今天和沈老師又學到了一招,(*^__^*) 嘻嘻……——游標的更高級的使用
相關字段有glstr , username , rename,pos以圖例講解幾者關系:
username:該會員的用戶名
prename: 該會員的上級接點會員的用戶名,如Bl,Br的prename都是A
pos: 該會員的位置,1=左,2=右
glstr: 樹狀圖所經過的節點,即該會員的所有上級接點,如C1r會員的glstr為 :A,Bl
問題:求取dg_users表中字段username的所有會員的左右兩邊的人數(左右子節點數);
解析:
1. 查詢出所有的username,遍歷結果集,
select? `username` from `dg_users` ;
2. 比如username為*A*的左右兩個直接子節點Y_left,Y_right(注:該會員可能不存在下級,也可能只有一個左子節點,或右子節點)
select `username`? ,`pos` from `dg_users` where `prename`='*A*';
(注:這里要判斷pos,為1時為左,為2時為右);
3.求Y_left,Y_right兩個子節點的子節點數count_L , count_R
select count(id) from `dg_users` where `glstr` likeCONCAT("%,",*A*,",%") orCONCAT("%,",*A*) orCONCAT(*A*,",%");
4. 加法計算,count_L+1,count_R+1就是username為**的左右子節點數了
update `dg_users` set `y_left`=count_L+1,`y_right`=count_R+1 where `username` = '*A*';
5.現在重點來啦!!!我們用前面學到的游標對上面的sql語句進行整理,(要用到兩個游標哦,好期待ing~~)
(1)、2,3步驟寫為一個游標函數:
```
BEGIN
declare_sibegin_pos VARCHAR(50);
DECLARE_sibegin_username VARCHAR(50);
DECLAREdone INT DEFAULT FALSE;
DECLAREcurCURSOR FORSELECT pos,username FROM jingluovip.dg_users WHERE glstr LIKE CONCAT(sibegin_username,"%");
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO _sibegin_pos,_sibegin_username;
IF done THEN
LEAVE read_loop;
END IF;
# 按用戶名稱查詢數據
IF _sibegin_pos = 1 THEN
# left
SELECT count(glstr) INTO out_left FROM jingluovip.dg_users WHERE glstr LIKE CONCAT("%,",_sibegin_username,",%") OR glstr LIKE CONCAT(_sibegin_username,",%") OR glstr LIKE CONCAT("%,",_sibegin_username);
ELSE
SELECT count(glstr) INTO out_right FROM jingluovip.dg_users WHERE glstr LIKE CONCAT("%,",_sibegin_username,",%") OR glstr LIKE CONCAT(_sibegin_username,",%") OR glstr LIKE CONCAT("%,",_sibegin_username);
END IF;
END LOOP;
CLOSE cur;
END
```
該函數命名為sp_user_jiesuan2
(2)、1,4步驟寫為一個游標函數:
```
DECLAREsibegin_username VARCHAR(50);
DECLAREsibegin_left INT;
DECLAREsibegin_right INT;
DECLARE done INT DEFAULT FALSE;
-- DECLARE cur CURSOR FOR SELECT `username` FROM jingluovip.dg_users_copy WHERE username = '13507378136';
DECLARE cur CURSOR FOR SELECT `username` FROM jingluovip.dg_users;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO sibegin_username;
IF done THEN
LEAVE read_loop;
END IF;
# 按用戶名稱查詢數據
call sp_user_jiesuan2(sibegin_username,@l,@r);
UPDATE jingluovip.dg_users SET jingluovip.dg_users.y_left = @l + 1, jingluovip.dg_users.y_right = @r + 1 WHERE username = sibegin_username;
END LOOP;
CLOSE cur;
END
```
6.結束語:
啦啦啦,怎么樣,是不是感覺很高大上(⊙o⊙)? 對沈老師的膜拜又上升了一個高度 O(∩_∩)O哈哈~