MySQL中的遞歸查詢主要通過WITH RECURSIVE
語句來實現,這在處理具有層級關系或樹形結構的數據時非常有用。下面將通過一個具體的例子來詳細解釋如何在MySQL中使用遞歸查詢。
示例場景
假設我們有一個部門表(departments
),其中包含部門的ID、部門名稱以及上級部門的ID(parent_id
)。現在,我們想要查詢出某個部門及其所有下級部門的名稱。
表結構
CREATE TABLE departments (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,parent_id INT,FOREIGN KEY (parent_id) REFERENCES departments(id)
);
插入數據
INSERT INTO departments (name, parent_id) VALUES ('總公司', NULL);
INSERT INTO departments (name, parent_id) VALUES ('技術部', 1);
INSERT INTO departments (name, parent_id) VALUES ('人事部', 1);
INSERT INTO departments (name, parent_id) VALUES ('前端開發', 2);
INSERT INTO departments (name, parent_id) VALUES ('后端開發', 2);
INSERT INTO departments (name, parent_id) VALUES ('UI設計', 2);
最終表如下圖:
遞歸查詢
現在,如果我們想要查詢出“技術部”及其所有下級部門的名稱,可以使用以下SQL語句:
WITH RECURSIVE SubDeps AS (-- 初始查詢,選擇頂級部門(技術部)SELECT id, name, parent_idFROM departmentsWHERE name = '技術部'UNION ALL-- 遞歸查詢,從當前已知部門中繼續查詢它們的下級部門SELECT d.id, d.name, d.parent_idFROM departments dINNER JOIN SubDeps sd ON d.parent_id = sd.id
)
SELECT * FROM SubDeps;
查詢結果如下圖:
解釋
- WITH RECURSIVE:這個語句開始了一個遞歸的公用表表達式(Common Table Expression, CTE)。
- SubDeps:這是CTE的名稱,在遞歸查詢中我們可以引用它。
- 初始查詢:首先,我們從
departments
表中選擇出頂級部門(這里是“技術部”)。 - UNION ALL:我們使用
UNION ALL
來合并初始查詢的結果和遞歸查詢的結果。UNION ALL
允許重復的行,如果確定不會有重復,也可以使用UNION
(但在這個例子中,由于我們可能查詢出多個層級的相同部門,所以使用UNION ALL
)。 - 遞歸查詢:在遞歸查詢中,我們從
departments
表中再次選擇數據,但這次我們選擇的是那些其parent_id
等于CTE中當前行的id
的行。這樣,我們就能找到所有下級部門。 - SELECT * FROM SubDeps:最后,我們從CTE中選擇所有結果。