SQL层级数据问题:将子项匹配到选定父项列表的T-SQL实现方案
实现方案
思路说明
核心逻辑是通过递归CTE从所有选中项出发向下遍历所有子节点,子节点直接继承最近的上级选中项的ID作为Tag,没有匹配到选中项祖先的节点Tag自动设为Null,天然支持选中项存在父子层级的场景。
测试表结构
先创建两张测试表用于验证:
-- 层级数据表 CREATE TABLE ChartHierarchy ( ID INT PRIMARY KEY, ParentID INT, Level NVARCHAR(50), Title NVARCHAR(10) ); -- 插入示例数据 INSERT INTO ChartHierarchy VALUES (10411, 9925, '1.1.4', 'A'), (10462, 10411, '1.1.4.1', 'B'), (10467, 10462, '1.1.4.1.1', 'C'), (10429, 10411, '1.1.4.2', 'D'), (10434, 10429, '1.1.4.2.1', 'E'), (10435, 10434, '1.1.4.2.1.4', 'F'), (10436, 10435, '1.1.4.2.1.4.3', 'G'), (10430, 10429, '1.1.4.2.3', 'H'), (10431, 10430, '1.1.4.2.3.3', 'I'), (10433, 10431, '1.1.4.2.3.3.1', 'J'), (10432, 10433, '1.1.4.2.3.3.1.1', 'K'); -- 选中项表,存储所有选中节点的ID CREATE TABLE SelectedLevels ( SelectedID INT PRIMARY KEY ); -- 插入示例中的加粗选中项 INSERT INTO SelectedLevels VALUES (10462), (10434), (10435), (10430);
核心查询代码
WITH RecursiveTags AS ( -- 锚点:选中项本身Tag为自身ID SELECT ID, ParentID, Level, ID AS Tag FROM ChartHierarchy WHERE ID IN (SELECT SelectedID FROM SelectedLevels) UNION ALL -- 递归遍历:选中项的所有子节点继承父节点Tag SELECT c.ID, c.ParentID, c.Level, rt.Tag FROM ChartHierarchy c INNER JOIN RecursiveTags rt ON c.ParentID = rt.ID -- 排除本身就是选中项的子节点,避免重复生成记录 WHERE c.ID NOT IN (SELECT SelectedID FROM SelectedLevels) ) SELECT c.ID, c.ParentID, c.Level, rt.Tag FROM ChartHierarchy c LEFT JOIN RecursiveTags rt ON c.ID = rt.ID ORDER BY c.Level;
注意事项
- 如果你的选中项表存储的是
Level字段值而非ID,只需把锚点的WHERE条件改为Level IN (SELECT Level FROM SelectedLevels)即可 - 2000行量级的数据执行效率无压力,哪怕后续数据规模上涨10倍也不会有性能问题
- 选中列表更新时只需修改
SelectedLevels表的内容,无需调整查询逻辑
内容的提问来源于stack exchange,提问作者babaganouj25
相关产品推荐
相关产品推荐

