通過sql實現傳入父級id查詢出所有的子集
最近剛好有個業務需要這樣實現個功能,就是在點擊查詢列表詳情的時候只會傳入父級id,而詳情得渲染出所有子集,那么做法有很多,可以直接通過代碼遞歸查詢去實現,
但很明顯效率低下,所有考慮了下純粹通過sql來實現這個功能點。
效果展示
如圖這個“水果”的數據其實是一個樹的數據,列表上所展示的是頂級數據,點擊詳情時傳入了頂級id,如何通過頂級id把他的子集全部找出來。
需要達到的效果是點擊詳情后展示出所有的樹型數據如
實現思路
首先我的這張表結構是這樣的:
CREATE TABLE `rule_entity_property` ( `id` varchar(32) NOT NULL COMMENT '主鍵', `app_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '應用編碼', `catalog_id` varchar(32) NOT NULL COMMENT '目錄ID', `parent_id` varchar(32) NOT NULL COMMENT '上級ID', `type` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '類型', `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '(實體或屬性)編碼', `code_path` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '(實體或屬性)完整編碼', `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '(實體或屬性)名稱', `descriptions` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '(實體或屬性)描述', `null_able` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '是否可空(1可空,0不可空)', `gmt_tenant` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 'master' COMMENT '租戶', `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間', `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后修改時間', `gmt_mfyname` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '最后修改人名稱', `gmt_creator` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '創建人', `gmt_crtname` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '創建人名稱', `gmt_modifiedby` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '最后修改人', `gmt_status` char(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '(1:不可刪,2:登陸需修改密碼)', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='規則實體屬性表';
在頁面中新增這塊的數據完后有如下數據:
SQL實現的語句:
SELECT t3.* FROM ( SELECT t1.*, t2.*, IF(FIND_IN_SET(parent_id, @pids) > 0, @pids := CONCAT(@pids, ',', id), '0') AS isChild FROM ( SELECT * FROM rule_entity_property WHERE gmt_status != '-1' ORDER BY name,parent_id,id ) AS t1, ( SELECT @pids := 這里是傳進來的頂級id ) AS t2 ) t3 WHERE t3.isChild != '0'
測試如下:
我傳入上圖中果子的id:634def6720c418f85c0228cae5ac5f26
查詢出的結果:
如上圖通過一句sql實現了該功能避免去做程序的遞歸操作。
小提示:其實這個sql主要是通過FIND_IN_SET函數去實現,很簡單,不清楚原理的可以去看看這個函數用法。