Java Php Mysql 递归查询 查询当前节点下的所有子节点 包含当前节点返回列表

Love The Way You Lie 2023-09-29 22:57 126阅读 0赞

递归查询

  • MySQL
      1. WITH RECURSIVE语法
      1. 子查询
      1. 函数
  • JAVA代码
    • Hutool 工具
    • 执行多次SQL
    • 执行一次SQL
  • PHP代码

在这里插入图片描述

MySQL

1. WITH RECURSIVE语法

使用了MySQL的WITH RECURSIVE语法。首先,它选取了当前节点作为起点,然后在递归的过程中找到了所有它的子节点。最后,它输出了所有找到的节点的标识符。
请注意将查询中的[当前节点的ID]替换为你要查询的节点的ID。

  1. WITH RECURSIVE cte AS (
  2. SELECT id, parent_id
  3. FROM tree_table
  4. WHERE id = [当前节点的ID]
  5. UNION ALL
  6. SELECT t.id, t.parent_id
  7. FROM tree_table t
  8. INNER JOIN cte ON t.parent_id = cte.id
  9. )
  10. SELECT id FROM cte;

2. 子查询

如果你使用的MySQL版本不支持WITH RECURSIVE语法,或者你想尝试不使用WITH RECURSIVE的方法;
这个查询使用了两个子查询。第一个子查询选取了当前节点的ID,并且作为递归查询的起点。第二个子查询从tree_table表中自联结,以查找当前节点的所有子节点。然后,使用JOIN操作将这些子节点与tree_table表中的原始记录匹配,从而得到当前节点下的所有子节点。
请注意将查询中的[当前节点的ID]替换为你要查询的节点的ID。

  1. SELECT t1.id
  2. FROM tree_table t1
  3. JOIN (
  4. SELECT id FROM tree_table WHERE id = [当前节点的ID]
  5. UNION ALL
  6. SELECT t2.id FROM tree_table t2 JOIN tree_table t3 ON t2.parent_id = t3.id
  7. WHERE t3.id = [当前节点的ID]
  8. ) t4
  9. ON t1.id = t4.id;

  1. SELECT
  2. r1.id,
  3. r1.name,
  4. r1.parent_id
  5. FROM
  6. your_table r1
  7. WHERE
  8. r1.parent_id =[当前节点的ID]
  9. UNION ALL
  10. SELECT
  11. r2.id,
  12. r2.name,
  13. r2.parent_id
  14. FROM
  15. your_table r2
  16. JOIN
  17. your_table r3
  18. ON r2.parent_id = r3.id
  19. WHERE
  20. r3.parent_id = [当前节点的ID]
  21. UNION ALL
  22. SELECT
  23. r4.id,
  24. r4.name,
  25. r4.parent_id
  26. FROM
  27. your_table r4
  28. JOIN
  29. your_table r5
  30. ON r4.parent_id = r5.id
  31. JOIN
  32. your_table r6
  33. ON r5.parent_id = r6.id
  34. WHERE
  35. r6.parent_id = [当前节点的ID]

3. 函数

编写一个存储过程或函数来实现递归查询;将查询中的[当前节点的ID]替换为你要查询的节点的ID。

  1. DELIMITER $$
  2. CREATE FUNCTION get_all_children (node_id INT) RETURNS TEXT
  3. BEGIN
  4. DECLARE child_ids TEXT DEFAULT '';
  5. DECLARE child_id INT;
  6. SELECT GROUP_CONCAT(id) INTO child_ids FROM tree_table WHERE parent_id = node_id;
  7. IF child_ids IS NOT NULL THEN
  8. SET child_ids = CONCAT(child_ids, ',', get_all_children(child_id));
  9. END IF;
  10. RETURN child_ids;
  11. END$$
  12. DELIMITER ;

这个函数使用递归的方式来查询当前节点下的所有子节点。首先,它查找所有直接子节点的ID,并使用GROUP_CONCAT函数将这些ID连接成一个逗号分隔的字符串。然后,对于每个子节点,函数递归调用自己来查找它的子节点,并将它们的ID也连接到返回值中。最后,函数返回一个包含当前节点下所有子节点ID的逗号分隔字符串。

请注意将函数中的tree_table和id和parent_id字段名称替换为你实际使用的表和字段名称。你可以使用以下语句来调用这个函数:

  1. SELECT get_all_children([当前节点的ID]);

将查询中的[当前节点的ID]替换为你要查询的节点的ID。

JAVA代码

Hutool 工具

  1. //创建配置
  2. TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
  3. // 自定义属性名 都要默认值的
  4. treeNodeConfig.setIdKey("id");
  5. treeNodeConfig.setNameKey("name");
  6. treeNodeConfig.setParentIdKey("parent_id");
  7. treeNodeConfig.setChildrenKey("child");
  8. // 最大递归深度 可以不设置
  9. treeNodeConfig.setDeep(3);
  10. /*
  11. * 形参:
  12. * list – 源数据集合
  13. * rootId – 最顶层父id值 一般为 0 之类
  14. * treeNodeConfig – 配置
  15. * nodeParser – 转换器
  16. * 返回值: List
  17. */
  18. // 构建树结构
  19. List<Tree<String>> build = TreeUtil.build(list, "0", treeNodeConfig, (treeNode, tree) -> {
  20. tree.setId(String.valueOf(treeNode.get("area_id")));
  21. tree.setParentId(String.valueOf(treeNode.get("parent_id")));
  22. tree.setName((CharSequence) treeNode.get("area_name"));
  23. });

执行多次SQL

这个Java方法使用递归的方式来查询当前节点下的所有子节点。首先,它查询所有直接子节点的ID。然后,对于每个子节点,方法递归调用自己来查找它的子节点。最后,方法返回一个包含当前节点下所有子节点ID的列表。

请注意将示例代码中的tree_table和id和parent_id字段名称替换为你实际使用的表和字段名称,以及将数据库连接的URL、用户名和密码替换为你的实际连接信息。

  1. import java.sql.*;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class TreeUtils {
  5. public static List<Integer> getAllChildren(int nodeId, Connection conn) throws SQLException {
  6. List<Integer> childIds = new ArrayList<>();
  7. // 查询所有直接子节点
  8. PreparedStatement stmt = conn.prepareStatement("SELECT id FROM tree_table WHERE parent_id = ?");
  9. stmt.setInt(1, nodeId);
  10. ResultSet rs = stmt.executeQuery();
  11. // 对于每个子节点,递归调用自己来查找它的子节点
  12. while (rs.next()) {
  13. int childId = rs.getInt("id");
  14. childIds.add(childId);
  15. childIds.addAll(getAllChildren(childId, conn));
  16. }
  17. rs.close();
  18. stmt.close();
  19. return childIds;
  20. }
  21. // 使用示例
  22. public static void main(String[] args) {
  23. Connection conn = null;
  24. try {
  25. // 创建数据库连接
  26. conn = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase", "root", "password");
  27. // 查询当前节点的所有子节点
  28. List<Integer> childIds = getAllChildren([当前节点的ID], conn);
  29. // 输出所有子节点的ID
  30. System.out.println(childIds);
  31. } catch (SQLException e) {
  32. e.printStackTrace();
  33. } finally {
  34. try {
  35. if (conn != null) {
  36. conn.close();
  37. }
  38. } catch (SQLException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. }
  43. }

执行一次SQL

这个Java方法首先执行SQL语句查询所有节点,然后将结果集转换为列表。接着使用递归的方式来查询树结构。它遍历列表中的每个节点,如果节点的父ID等于指定的父ID,则将该节点作为当前节点,递归查询该节点的子节点,并将子节点作为嵌套的子树添加到当前节点。最后,方法返回一个包含根节点的树结构的Map对象。

请注意将示例代码中的tree_table和id和parent_id字段名称替换为你实际使用的表和字段名称,以及将数据库连接的URL、用户名和密码

  1. import java.sql.*;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. public class TreeUtils {
  7. public static Map<String, Object> buildTree(List<Map<String, Object>> list, int parentId) {
  8. Map<String, Object> node = new HashMap<>();
  9. for (Map<String, Object> item : list) {
  10. int id = (int) item.get("id");
  11. int pid = (int) item.get("parent_id");
  12. if (pid == parentId) {
  13. // 设置当前节点的属性
  14. node.put("id", id);
  15. node.put("name", item.get("name"));
  16. // 递归查询当前节点的子节点
  17. List<Map<String, Object>> children = new ArrayList<>();
  18. for (Map<String, Object> child : list) {
  19. int childPid = (int) child.get("parent_id");
  20. if (childPid == id) {
  21. children.add(buildTree(list, id));
  22. }
  23. }
  24. // 如果有子节点,则将子节点添加到当前节点
  25. if (!children.isEmpty()) {
  26. node.put("children", children);
  27. }
  28. }
  29. }
  30. return node;
  31. }
  32. // 使用示例
  33. public static void main(String[] args) {
  34. Connection conn = null;
  35. try {
  36. // 创建数据库连接
  37. conn = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase", "root", "password");
  38. // 执行SQL语句查询所有节点
  39. PreparedStatement stmt = conn.prepareStatement("SELECT * FROM tree_table");
  40. ResultSet rs = stmt.executeQuery();
  41. // 将结果集转换为列表
  42. List<Map<String, Object>> list = new ArrayList<>();
  43. while (rs.next()) {
  44. Map<String, Object> item = new HashMap<>();
  45. item.put("id", rs.getInt("id"));
  46. item.put("name", rs.getString("name"));
  47. item.put("parent_id", rs.getInt("parent_id"));
  48. list.add(item);
  49. }
  50. // 构建树结构
  51. Map<String, Object> tree = buildTree(list, 0);
  52. // 输出树结构
  53. System.out.println(tree);
  54. rs.close();
  55. stmt.close();
  56. } catch (SQLException e) {
  57. e.printStackTrace();
  58. } finally {
  59. try {
  60. if (conn != null) {
  61. conn.close();
  62. }
  63. } catch (SQLException e) {
  64. e.printStackTrace();
  65. }
  66. }
  67. }
  68. }

PHP代码

这个PHP函数使用递归的方式来查询当前节点下的所有子节点。首先,它查询所有直接子节点的ID。然后,对于每个子节点,函数递归调用自己来查找它的子节点。最后,函数返回一个包含当前节点下所有子节点ID的数组。

请注意将示例代码中的tree_table和id和parent_id字段名称替换为你实际使用的表和字段名称。如果你使用的是其他语言或框架,可以根据类似的逻辑编写递归函数或方法来实现递归查询。

  1. function get_all_children($node_id, $mysqli) {
  2. $child_ids = array();
  3. // 查询所有直接子节点
  4. $result = $mysqli->query("SELECT id FROM tree_table WHERE parent_id = $node_id");
  5. // 对于每个子节点,递归调用自己来查找它的子节点
  6. while ($row = $result->fetch_assoc()) {
  7. $child_id = $row['id'];
  8. $child_ids[] = $child_id;
  9. $child_ids = array_merge($child_ids, get_all_children($child_id, $mysqli));
  10. }
  11. return $child_ids;
  12. }
  13. // 使用示例
  14. $mysqli = new mysqli('host', 'username', 'password', 'database');
  15. $node_id = 1; // 替换为你要查询的节点的ID
  16. $child_ids = get_all_children($node_id, $mysqli);
  17. print_r($child_ids);

发表评论

表情:
评论列表 (有 0 条评论,126人围观)

还没有评论,来说两句吧...

相关阅读