如何查询二级父子表中无子女的父节点及各父节点的最后子节点
解决方案
针对你这个仅两级的父子表结构,我们可以把需求拆成两部分查询,再用UNION ALL合并结果,具体如下:
1. 查询无子女的父节点
这部分要找的是本身是父节点(ParentId IS NULL)且没有任何子节点的记录,用NOT EXISTS来判断效率很高:
SELECT Id, Description, ParentId FROM YourTableName WHERE ParentId IS NULL AND NOT EXISTS ( SELECT 1 FROM YourTableName AS Child WHERE Child.ParentId = YourTableName.Id )
2. 查询每个有子女的父节点的最后一个子节点
这里默认以自增的Id作为“最后一个”的判断依据(因为Id是IDENTITY,越大的Id越晚创建),如果需要按其他字段排序,替换MAX(Id)即可:
SELECT Child.Id, Child.Description, Child.ParentId FROM YourTableName AS Child INNER JOIN ( -- 先找出每个父节点对应的最大子节点Id SELECT ParentId, MAX(Id) AS LastChildId FROM YourTableName WHERE ParentId IS NOT NULL GROUP BY ParentId ) AS ParentMax ON Child.Id = ParentMax.LastChildId
完整合并后的SQL
把两部分结果合并(用UNION ALL比UNION更高效,因为不需要去重):
-- 无子女的父节点 SELECT Id, Description, ParentId FROM YourTableName WHERE ParentId IS NULL AND NOT EXISTS ( SELECT 1 FROM YourTableName AS Child WHERE Child.ParentId = YourTableName.Id ) UNION ALL -- 有子女的父节点的最后一个子节点 SELECT Child.Id, Child.Description, Child.ParentId FROM YourTableName AS Child INNER JOIN ( SELECT ParentId, MAX(Id) AS LastChildId FROM YourTableName WHERE ParentId IS NOT NULL GROUP BY ParentId ) AS ParentMax ON Child.Id = ParentMax.LastChildId
补充说明
如果你的“最后一个子节点”不是按Id排序,而是按其他字段(比如创建时间CreateTime),只需要修改子查询里的MAX(Id)为MAX(CreateTime),同时关联条件调整为Child.CreateTime = ParentMax.LastChildTime即可。
内容的提问来源于stack exchange,提问作者user2961942
相关产品推荐
相关产品推荐

