需求说明
有表 t_dept_info
,它有dept_id
、dept_name
、p_dept_id
三个关键字段,有一家公司,他们的部门分为四级。现需要取出任意部门下所有没有下级部门的部门。以下面的组织架构为例,
有的部门在二级,有的在三级上,如果使用常规的 sql 自关联的方法,不能适应情况的发展,如果,在第四级或者第六级上面新增部门。那就需要修改 sql 了。
解决办法
- 可以将部门理解为一棵树,使用递归的方式遍历上面所有叶子节点(没有子树的节点,也就是没有下级部门的部门)
- 使用栈的数据结构遍历到叶子节点。这种方式从原理上比递归是快的。
递归的方式:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
/**
* @className: LoadDeptInfo
* @Description:
* @Author: wangyifei
* @Date: 2024/7/12 9:27
*/
public class LoadDeptInfo {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://IP:3306/DB";
static final String USER = "user";
static final String PASS = "pwd";
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 注册 JDBC 驱动
Class.forName(JDBC_DRIVER);
// 打开连接
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// SQL 查询语句
String sql = "SELECT dept_id, dept_name, p_dept_id FROM DB.t_dept "
+ "where company_id = 5 ";
// 创建预处理语句
pstmt = conn.prepareStatement(sql);
// 执行查询
rs = pstmt.executeQuery();
// 处理结果集
Map<String , Dept> depts = new HashMap<>();
while (rs.next()) {
// 根据字段名称取出数据
String deptId = rs.getString("dept_id");
String deptName = rs.getString("dept_name");
String pDeptId = rs.getString("p_dept_id");
depts.put( deptId , new Dept(deptId + "" , deptName , pDeptId+""));
}
// System.out.println(depts.size());
List<String> result = getDeptInfo(depts , 18960 + "");
System.out.println(String.join("\nunion all" , result));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException se) {
se.printStackTrace();
}
}
}
public static boolean hasChildren(Map<String , Dept> depts , String pDeptId){
Collection<Dept> values = depts.values();
for (Dept value : values) {
if(pDeptId.equals(value.getpDeptId())){
return true ;
}
}
return false ;
}
public static List<String> getDeptInfo(Map<String , Dept> depts , String deptId) {
List<String> rs = new ArrayList<>();
if(!hasChildren(depts , deptId)){
return null ;
}else{
Collection<Dept> values = depts.values();
for(Dept v : values){
if(deptId.equals(v.getpDeptId())){
List<String> deptInfo = getDeptInfo(depts, v.getDeptId());
if(null != deptInfo){
rs.addAll(deptInfo);
}else{
rs.add(" select " + v.getDeptId() + " as dept_id , '"
+ v.getDeptName() + "' as dept_name ");
}
}
}
}
return rs;
}
public static class Dept{
private String deptId ;
private String deptName ;
private String pDeptId ;
public String getDeptId() {
return deptId;
}
public void setDeptId(String deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getpDeptId() {
return pDeptId;
}
public void setpDeptId(String pDeptId) {
this.pDeptId = pDeptId;
}
public Dept(String deptId, String deptName, String pDeptId) {
this.deptId = deptId;
this.deptName = deptName;
this.pDeptId = pDeptId;
}
}
}
利用栈的方式
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;
/**
* @className: LoadDeptInfo
* @Description:
* @Author: wangyifei
* @Date: 2024/7/12 9:27
*/
public class LoadDeptInfo {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://IP:3306/DB";
static final String USER = "user";
static final String PASS = "pwd";
static final Map<String , List<Dept>> parentChildren = new HashMap<>();
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 注册 JDBC 驱动
Class.forName(JDBC_DRIVER);
// 打开连接
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// SQL 查询语句
String sql = "SELECT dept_id, dept_name, p_dept_id FROM DB.t_dept "
+ "where company_id = 5 ";
// 创建预处理语句
pstmt = conn.prepareStatement(sql);
// 执行查询
rs = pstmt.executeQuery();
// 处理结果集
Map<String , Dept> depts = new HashMap<>();
while (rs.next()) {
// 根据字段名称取出数据
String deptId = rs.getString("dept_id");
String deptName = rs.getString("dept_name");
String pDeptId = rs.getString("p_dept_id");
depts.put( deptId , new Dept(deptId + "" , deptName , pDeptId+""));
}
// System.out.println(depts.size());
List<String> result = getDeptInfo1(depts , 18960 + "");
System.out.println(String.join("\nunion all" , result));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException se) {
se.printStackTrace();
}
}
}
public static boolean hasChildren(Map<String , Dept> depts , String pDeptId){
Collection<Dept> values = depts.values();
Set<String> strings = parentChildren.keySet();
if(strings.contains(pDeptId)){
return true ;
}
for (Dept value : values) {
if(pDeptId.equals(value.getpDeptId())){
parentChildren.computeIfPresent(pDeptId , (key , o ) -> {
o.add(value);
return o ;
});
parentChildren.putIfAbsent(pDeptId , new ArrayList<Dept>(){
{add(value);}
});
return true ;
}
}
return false ;
}
public static List<String> getDeptInfo1(Map<String , Dept> depts , String parentDeptId){
List<String> leafDept = new ArrayList<>();
Collection<Dept> values = depts.values();
Stack<Dept> stack = new Stack<>();
stack.push(depts.get(parentDeptId));
while(!stack.isEmpty()){
Dept pop = stack.pop();
List<Dept> children = findChildren(depts, pop.getDeptId());
if(Objects.isNull(children) || children.isEmpty()){
leafDept.add(" select " + pop.getDeptId() + " as dept_id , '"
+ pop.getDeptName() + "' as dept_name ");
}
for (Dept child : children) {
stack.push(child);
}
}
return leafDept ;
}
public static List<Dept> findChildren(Map<String , Dept> depts ,String deptId){
List<Dept> collect = depts.values().stream().filter(x -> !parentChildren.containsKey(x.getDeptId()) && null != x.getpDeptId() && x.getpDeptId().equals(deptId)).collect(Collectors.toList());
parentChildren.computeIfPresent(deptId , (key , o ) -> {
o.addAll(collect);
return o ;
});
parentChildren.putIfAbsent(deptId , collect);
return collect ;
}
public static class Dept{
private String deptId ;
private String deptName ;
private String pDeptId ;
public String getDeptId() {
return deptId;
}
public void setDeptId(String deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getpDeptId() {
return pDeptId;
}
public void setpDeptId(String pDeptId) {
this.pDeptId = pDeptId;
}
public Dept(String deptId, String deptName, String pDeptId) {
this.deptId = deptId;
this.deptName = deptName;
this.pDeptId = pDeptId;
}
}
}