经常有业务需要递归查询MySQL树形结构某一节点的所有子节点,每次从网上扒拉找都得找半天,索性就自己总结一些自己遇到的比较好用的一些方法。
SQL方法一:
SELECT * FROM ( SELECT t1.*, IF ( FIND_IN_SET( parent_id, @parent_ids ) > 0, @parent_ids := CONCAT( @parent_ids, ',', id ), '0' ) AS ischild FROM ( SELECT * FROM blade_menu AS t WHERE t.is_deleted = 0 AND client_type = 'dianduyun_app' ORDER BY t.id ASC ) t1, ( SELECT @parent_ids := '1508255373140103170' ) t2 ) t3 WHERE ischild != '0'
需要修改的地方
- parent_id,改为你的父级id字段
- blade_menu ,改为你的表名称
- WHERE t.is_deleted = 0 ,改为你的查询条件
- @parent_ids := ‘1508255373140103170’,值改为你要传入的父级id
执行结果
SQL方法二:
SELECT rd.* FROM ( SELECT * FROM fine_authority_object WHERE parentId IS NOT NULL AND is_deleted = 0 ) rd, ( SELECT @pid := '2342465874553522423' ) pd WHERE FIND_IN_SET( parentId, @pid ) > 0 AND @pid := concat( @pid, ',', id ) UNION SELECT * FROM fine_authority_object WHERE FIND_IN_SET( id, @pid ) > 0;
需要修改的地方
fine_authority_object ,改为你的表名,以及后面的查询条件进行修改。
SELECT @pid := ‘2342465874553522423’ ,值改为你要传的父id的值
FIND_IN_SET( parentId, @pid ) ,parentId改为你的父级id字段名
备注:
- 当前这条SQL是根据多个父节点查询所有子节点(包含自身)
- 如果不想查询结果包含自身,去掉后边的union
执行结果示例
Java List转树形结构
另外再分享一个将上面查询出来的list给转成树形结构的形式给前端返回的一个工具类。
public static List<ReportTemplateVo> listToTree2(List<ReportTemplateVo> list) { List<ReportTemplateVo> tree = new ArrayList<>(); for (ReportTemplateVo ReportTemplateVo : list) { //找到根节点 if (ReportTemplateVo.getParentId().equals("reportlets")) { tree.add(findChildren(ReportTemplateVo, list)); } } return tree; } /** * 查找ReportTemplateVo的子节点 * @param ReportTemplateVo * @param list * @return */ private static ReportTemplateVo findChildren(ReportTemplateVo ReportTemplateVo, List<ReportTemplateVo> list) { List<ReportTemplateVo> children = new ArrayList<>(); for (ReportTemplateVo node : list) { if (node.getParentId().equals(ReportTemplateVo.getId())) { //递归调用 children.add(findChildren(node, list)); } } ReportTemplateVo.setChildren(children); return ReportTemplateVo; }
ReportTemplateVo实体:
public class ReportTemplateVo { private static final long serialVersionUID = 1L; /** * 主键ID */ private String id; /** * 父节点ID */ private String parentId; /** * 子孙节点 */ private List<ReportTemplateVo> children; @ApiModelProperty("节点是否可以被选中") private Boolean disabled; /** * 节点名称 */ @ApiModelProperty("节点名称") private String title;
总结
这两种方法都可以查询到自己想要的数据。然后调用这个方法可以直接生成相应的树形结构,这种东西很常用,又懒得自己写, 所以勤记录,多做备份会省很多事儿,
最后,愿大家都乐意分享一些高效开发小工具,减少重复造轮子~