NativeSqlJoinOptimizer.java 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package com.kingdee.eas.custom.dataconfig.utils;
  2. import net.sf.jsqlparser.JSQLParserException;
  3. import net.sf.jsqlparser.expression.Expression;
  4. import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
  5. import net.sf.jsqlparser.parser.CCJSqlParserUtil;
  6. import net.sf.jsqlparser.schema.Column;
  7. import net.sf.jsqlparser.schema.Table;
  8. import net.sf.jsqlparser.statement.Statement;
  9. import net.sf.jsqlparser.statement.select.*;
  10. import net.sf.jsqlparser.util.TablesNamesFinder;
  11. import java.util.*;
  12. public class NativeSqlJoinOptimizer {
  13. public String cleanRedundantJoins(String originalSql) throws JSQLParserException {
  14. // 1. 解析SQL
  15. Statement statement = CCJSqlParserUtil.parse(originalSql);
  16. Select select = (Select) statement;
  17. PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
  18. // 2. 提取所有被使用的表名(用内置工具类,更稳定)
  19. Set<String> usedTables = getUsedTables(plainSelect);
  20. System.out.println("被使用的表:" + usedTables); // 输出 [t1, t2]
  21. // 3. 过滤冗余JOIN
  22. List<Join> filteredJoins = new ArrayList<>();
  23. if (plainSelect.getJoins() != null) {
  24. for (Join join : plainSelect.getJoins()) {
  25. if (join.getRightItem() instanceof Table) {
  26. Table joinTable = (Table) join.getRightItem();
  27. String tableName = joinTable.getName();
  28. if (usedTables.contains(tableName)) {
  29. filteredJoins.add(join);
  30. }
  31. }
  32. }
  33. }
  34. // 4. 重构SQL
  35. plainSelect.setJoins(filteredJoins);
  36. String optimizedSql = plainSelect.toString();
  37. System.out.println("优化后的SQL:" + optimizedSql);
  38. return optimizedSql;
  39. }
  40. /**
  41. * 提取使用的表名(不依赖SelectExpressionItem)
  42. */
  43. private static Set<String> getUsedTables(PlainSelect plainSelect) {
  44. Set<String> usedTables = new HashSet<>();
  45. TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
  46. // 1. 提取主表(FROM)
  47. if (plainSelect.getFromItem() instanceof Table) {
  48. Table fromTable = (Table) plainSelect.getFromItem();
  49. usedTables.add(fromTable.getName());
  50. }
  51. // 2. 提取SELECT字段中的表(遍历Column,直接获取表名)
  52. for (SelectItem item : plainSelect.getSelectItems()) {
  53. // 直接遍历Item中的Column,绕过SelectExpressionItem
  54. item.accept(new SelectItemVisitorAdapter() {
  55. public void visit(Column column) {
  56. if (column.getTable() != null) {
  57. usedTables.add(column.getTable().getName());
  58. }
  59. }
  60. });
  61. }
  62. // 3. 提取WHERE条件中的表(用内置工具类)
  63. if (plainSelect.getWhere() != null) {
  64. List<String> whereTables = tablesNamesFinder.getTableList(plainSelect.getWhere());
  65. usedTables.addAll(whereTables);
  66. }
  67. return usedTables;
  68. }
  69. }