Mysql
sql 或 hql 查詢以查找特定記錄的所有父項
我需要一個 sql 或 hql 查詢來查找特定記錄的所有父母,這應該在 oracle 和 mysql 中工作,例如,如果我有 id:201,父母將是:188、187、1。任何幫助都會不勝感激,謝謝
2011 年 10 月 24 日,我編寫了一些儲存函式來執行祖先和後代遍歷(查找分層欄位的最高級別:有 vs 沒有 CTE)。從我的文章中,您將使用
GetAncestry
. 從您的數據中,程式碼GetAncestry
將遍歷,直到它被-1
視為父 ID。parent_id
除了更改為之外,不需要更改算法parent
。為了舉例,讓我們假設表被稱為
mydb.mytable
獲取祖先程式碼
USE mydb DELIMITER $$ DROP FUNCTION IF EXISTS `GetAncestry` $$ CREATE FUNCTION `GetAncestry` (GivenID INT) RETURNS VARCHAR(1024) DETERMINISTIC BEGIN DECLARE rv VARCHAR(1024); DECLARE cm CHAR(1); DECLARE ch INT; SET rv = ''; SET cm = ''; SET ch = GivenID; WHILE ch > 0 DO SELECT IFNULL(parent,-1) INTO ch FROM (SELECT parent FROM mytable WHERE id = ch) A; IF ch > 0 THEN SET rv = CONCAT(rv,cm,ch); SET cm = ','; END IF; END WHILE; RETURN rv; END $$ DELIMITER ;
創建此儲存過程後,您將按如下方式呼叫該函式:
USE mydb SELECT GetAncestry(201);
讓我們測試一下
基於您的問題的範例數據
drop database if exists mydb; create database mydb; use mydb create table mytable (id int not null, name varchar(20), parent int default -1, primary key (id)); insert into mytable values (1,'ROOT',-1),(162,'ROOT',1),(163,'ROOT',1),(164,'ROOT',1), (165,'ROOT',1),(166,'ROOT',1),(167,'ROOT',1),(168,'ROOT',1), (169,'ROOT',1),(170,'ROOT',1),(171,'ROOT',1),(172,'ROOT',1), (173,'ROOT',1),(174,'ROOT',1),(175,'ROOT',1),(176,'ROOT',1), (177,'ROOT',1),(178,'ROOT',1),(179,'ROOT',1),(180,'ROOT',1), (181,'ROOT',1),(182,'ROOT',1),(183,'ROOT',1),(184,'ROOT',1), (185,'ROOT',184),(186,'ROOT',1),(187,'ROOT',1),(188,'ROOT',187), (201,'ROOT',188),(202,'ROOT',201),(203,'ROOT',202);
載入樣本數據
mysql> drop database if exists mydb; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> create database mydb; Query OK, 1 row affected (0.00 sec) mysql> use mydb Database changed mysql> create table mytable -> (id int not null, -> name varchar(20), -> parent int default -1, -> primary key (id)); Query OK, 0 rows affected (0.02 sec) mysql> insert into mytable values -> (1,'ROOT',-1),(162,'ROOT',1),(163,'ROOT',1),(164,'ROOT',1), -> (165,'ROOT',1),(166,'ROOT',1),(167,'ROOT',1),(168,'ROOT',1), -> (169,'ROOT',1),(170,'ROOT',1),(171,'ROOT',1),(172,'ROOT',1), -> (173,'ROOT',1),(174,'ROOT',1),(175,'ROOT',1),(176,'ROOT',1), -> (177,'ROOT',1),(178,'ROOT',1),(179,'ROOT',1),(180,'ROOT',1), -> (181,'ROOT',1),(182,'ROOT',1),(183,'ROOT',1),(184,'ROOT',1), -> (185,'ROOT',184),(186,'ROOT',1),(187,'ROOT',1),(188,'ROOT',187), -> (201,'ROOT',188),(202,'ROOT',201),(203,'ROOT',202); Query OK, 31 rows affected (0.01 sec) Records: 31 Duplicates: 0 Warnings: 0 mysql>
創建儲存函式
mysql> USE mydb Database changed mysql> DELIMITER $$ mysql> DROP FUNCTION IF EXISTS `GetAncestry` $$ Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> CREATE FUNCTION `GetAncestry` (GivenID INT) RETURNS VARCHAR(1024) -> DETERMINISTIC -> BEGIN -> DECLARE rv VARCHAR(1024); -> DECLARE cm CHAR(1); -> DECLARE ch INT; -> -> SET rv = ''; -> SET cm = ''; -> SET ch = GivenID; -> WHILE ch > 0 DO -> SELECT IFNULL(parent,-1) INTO ch FROM -> (SELECT parent FROM mytable WHERE id = ch) A; -> IF ch > 0 THEN -> SET rv = CONCAT(rv,cm,ch); -> SET cm = ','; -> END IF; -> END WHILE; -> RETURN rv; -> END $$ Query OK, 0 rows affected (0.00 sec) mysql> DELIMITER ;
呼叫 GetAncestry
mysql> SELECT GetAncestry(201); +------------------+ | GetAncestry(201) | +------------------+ | 188,187,1 | +------------------+ 1 row in set (0.00 sec) mysql>
只剩下一件事要做…
試一試 !!!
我已經多次討論在 DBA StackExchange 中使用 GetAncestry
請注意,這是特定於 MySQL 的答案。如果您希望在 PL/SQL 塊或儲存過程中實現算法,請閱讀 PL/SQL 文件。