【MySQL】遞歸查詢


MySQL8.0版本以上支持遞歸查詢 CTE

遞歸 CTE語法規則

WITH RECURSIVE cte_name[(col_name [, col_name] ...)] AS (
    initial_query  -- anchor member
    UNION ALL
    recursive_query -- recursive member that references to the CTE name
)
SELECT * FROM cte_name;
遞歸CTE由三個主要部分組成:
  • 形成CTE結構的基本結果集的初始查詢(initial_query),初始查詢部分被稱為錨成員。
  • 遞歸查詢部分是引用CTE名稱的查詢,因此稱為遞歸成員。遞歸成員由一個UNIONUNION ALL或者UNION DISTINCT運算符與錨成員相連。
  • 終止條件是當遞歸成員沒有返回任何行時,確保遞歸停止。
遞歸CTE的執行順序如下:
  1. 首先,將成員分為兩個:錨點和遞歸成員。
  2. 接下來,執行錨成員形成基本結果集(R0),並使用該基本結果集進行下一次迭代。
  3. 然后,將Ri結果集作為輸入執行遞歸成員,並將Ri+1作為輸出。
  4. 之后,重復第三步,直到遞歸成員返回一個空結果集,換句話說,滿足終止條件。
  5. 最后,使用UNION ALL運算符將結果集從R0Rn組合。

遞歸示例

遞歸輸出1-10序列
WITH RECURSIVE seq_num(n) as (
	select 1
	UNION ALL
	select n+1 from seq_num where n < 10
)
select * from seq_num;
遞歸由下向上查詢
WITH RECURSIVE organ_rec (organCode,parentCode)as (
	select organCode,parentCode from g_organ where organCode ='101.007.009.004.011'
	UNION ALL
	select g.organCode,g.parentCode from g_organ g INNER JOIN organ_rec  on  organ_rec.parentCode = g.organCode
)
select organCode,parentCode from organ_rec;
遞歸由上往下查詢
WITH RECURSIVE organ_rec (organCode,parentCode)as (
	select organCode,parentCode from g_organ where parentCode ='-1'
	UNION ALL
	select g.organCode,g.parentCode from g_organ g INNER JOIN organ_rec  on  organ_rec.organCode = g.parentCode
)
select organCode,parentCode from organ_rec;
行轉列
SET  @str ='張三,李四,王五';
WITH RECURSIVE help_topic(help_topic_id) as (
	select 1
	UNION ALL
	select help_topic_id+1 from help_topic where help_topic_id < 10
),
temp_table AS (
select b.help_topic_id,SUBSTRING_INDEX(SUBSTRING_INDEX(@str,',',b.help_topic_id+1),',',-1)
from help_topic b where b.help_topic_id < LENGTH(@str) - LENGTH(REPLACE(@str,',','')) + 1)
select * from temp_table

遞歸CTE的限制

遞歸CTE的查詢語句中需要包含一個終止遞歸查詢的條件。當由於某種原因在遞歸CTE的查詢語句中未設置終止條件時,MySQL會根據相應的配置信息,自動終止查詢並拋出相應的錯誤信息。在MySQL中默認提供了如下兩個配置項來終止遞歸CTE。

  • cte_max_recursion_depth:如果在定義遞歸CTE時沒有設置遞歸終止條件,當達到cte_max_recursion_depth參數設置的執行次數后,MySQL會報錯。
  • max_execution_time:表示SQL語句執行的最長毫秒時間,當SQL語句的執行時間超過此參數設置的值時,MySQL報錯。

查看cte_max_recursion_depth參數的默認值,並設置。

--- 默認1000
SHOW VARIABLES LIKE 'cte_max%';
--- 會話級別設置該值
SET SESSION cte_max_recursion_depth=999999999;

查看MySQL中max_execution_time參數的默認值,並設置。

--- 0:表示沒有限制
SHOW VARIABLES LIKE 'max_execution%';
---單位為毫秒
SET SESSION max_execution_time=1000; 

總結

遞歸查詢時,如果是由上往下查詢時,建議通過類似層級碼或者樹型碼字段,通過關鍵字 LIKE 查詢。

參考:

  1. https://www.yiibai.com/mysql/recursive-cte.html
  2. 《MySQL技術大全》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM