find_in_set 函式
函式語法:find_in_set(str,strlist)
str 代表要查詢的字串 , strlist 是乙個以逗號分隔的字串,如 ('a,b,c')。
此函式用於查詢 str 字串在字串 strlist 中的位置,返回結果為 1 ~ n 。若沒有找到,則返回0。
concat:它用於連線n個字串
concat_ws :concat 是以逗號為預設的分隔符,而 concat_ws 則可以指定分隔符,第乙個引數傳入分隔符,如以下劃線分隔。
group_concat:可以分組的同時,把字段以特定分隔符拼接成字串
用法:group_concat( [distinct] 要連線的字段 [order by 排序字段 asc/desc ] [separator '分隔符'] )
先開啟自定義函式的功能:
在.ini中新增:
log-bin-trust-function-creators=1
delimiter $$
drop function if exists get_child_list$$
create function get_child_list(in_id varchar(10)) returns varchar(1000)
begin
declare ids varchar(1000) default '';
declare tempids varchar(1000);
set tempids = in_id;
while tempids is not null do
set ids = concat_ws(',',ids,tempids);
select group_concat(id) into tempids from dept where find_in_set(pid,tempids)>0;
end while;
return ids;
enddelimiter ;
(1) delimiter $$ ,用於定義結束符。我們知道 mysql 預設的結束符為分號,表明指令結束並執行。但是在函式體中,有時我們希望遇到分號不結束,因此需要暫時把結束符改為乙個隨意的其他值。我這裡設定為 $$,意思是遇到 $$ 才結束,並執行當前語句。
(2)drop function if exists get_child_list$$ 。若函式 get_child_list 已經存在了,則先刪除它。注意這裡需要用 當前自定義的結束符 $$ 來結束並執行語句。因為,這裡需要數和下邊的函體單獨區分開來執行
(3)create function get_child_list 建立函式。並且引數傳入乙個根節點的子節點id,需要注意一定要註明引數的型別和長度,如這裡是 varchar(10)。returns varchar(1000) 用來定義返回值引數型別。
(4)begin 和 end 中間包圍的就是函式體。用來寫具體的邏輯。
(5)declare 用來宣告變數,並且可以用 default 設定預設值。這裡定義的 ids 即作為整個函式的返回值,是用來拼接成最終我們需要的以逗號分隔的遞迴串的。而 tempids 是為了記錄下邊 while 迴圈中臨時生成的所有子節點以逗號拼接成的字串。
(6) set 用來給變數賦值。此處把傳進來的根節點賦值給 tempids 。
(7) while do ... end while; 迴圈語句,迴圈邏輯包含在內。注意,end while 末尾需要加上分號。
迴圈體內,先用 concat_ws 函式把最終結果 ids 和 臨時生成的 tempids 用逗號拼接起來。
然後以 find_in_set(pid,tempids)>0 為條件,遍歷在 tempids 中的所有 pid ,尋找以此為父節點的所有子節點 id ,並且通過 group_concat(id) into tempids 把這些子節點 id 都用逗號拼接起來,並覆蓋更新 tempids 。
等下次迴圈進來時,就會再次拼接 ids ,並再次查詢所有子節點的所有子節點。迴圈往復,一層一層的向下遞迴遍歷子節點。直到判斷 tempids 為空,說明所有子節點都已經遍歷完了,就結束整個迴圈。
(8)return ids; 用於把 ids 作為函式返回值返回。
(9)函式體結束以後,記得用結束符 $$ 來結束整個邏輯,並執行。
(10)最後別忘了,把結束符重新設定為預設的結束符分號 。
以上是向下遞迴查詢所有子節點的,並且包括了當前節點.
向上遞迴:
向上遞迴時,每一層遞迴乙個子節點只對應乙個父節點
用到了 group_concat 函式來拼接字串。但是,需要注意它是有長度限制的,預設為 1024 位元組。可以通過show variables like "group_concat_max_len";來檢視。
單位是位元組,不是字元。在 mysql 中,單個字母佔1個位元組,而我們平時用的 utf-8下,乙個漢字佔3個位元組。
這個對於遞迴查詢還是非常致命的。因為一般遞迴的話,關係層級都比較深,很有可能超過最大長度。(儘管一般拼接的都是數字字串,即單位元組)
兩種方法解決這個問題:
修改 mysql 配置檔案 my.cnf ,增加group_concat_max_len = 102400 #你要的最大長度。
執行以下任意乙個語句。set global group_concat_max_len=102400;或者set session group_concat_max_len=102400;
他們的區別在於,global是全域性的,任意開啟乙個新的會話都會生效,但是注意,已經開啟的當前會話並不會生效。而 session 是只會在當前會話生效,其他會話不生效。
共同點是,它們都會在 mysql 重啟之後失效,以配置檔案中的配置為準。所以,建議直接修改配置檔案。102400 的長度一般也夠用了。假設乙個id的長度為10個位元組,也能拼上一萬個id了。
使用 group_concat 函式還有乙個限制,就是不能同時使用 limit
如果需要的話,可以通過子查詢來實現
select group_concat(id) from (select * from dept limit 5) d;
mysql省市區遞迴查詢 mysql 遞迴查詢
insert into t areainfo values 1 0 中國 0 0 insert into t areainfo values 2 0 華北區 1 0 insert into t areainfo values 3 0 華南區 1 0 insert into t areainfo va...
mysql with 遞迴 mysql遞迴
sql server可以用with as 語法,mysql沒有這個功能,只能用別的方式了,目前的mysql版本中並不支援直接的遞迴查詢,但是通過遞迴到迭代轉化的思路,還是可以在一句sql內實現樹的遞迴查詢的。這個得益於mysql允許在sql語句內使用 變數。以下是示例 建立 create table...
mysql遞迴查詢統計 mysql遞迴查詢
樣例資料 create table treenodes id int primary key,nodename varchar 20 pid int select from treenodes id nodename pid 1 a 0 2 b 1 3 c 1 4 d 2 5 e 2 6 f 3 7...