指标库:原子指标编辑页:输出查询
This commit is contained in:
parent
b095d6926c
commit
bec249ced3
@ -46,4 +46,11 @@ public class TargetController {
|
||||
List<String> result = targetService.searchColumn(params);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "指标输出查询")
|
||||
@PostMapping("/getResult")
|
||||
public R<String> getResult(@RequestBody JSONObject params) {
|
||||
String result = targetService.getResult(params);
|
||||
return R.ok(result);
|
||||
}
|
||||
}
|
||||
|
@ -17,4 +17,6 @@ public interface TargetService extends IService<Target> {
|
||||
IPage<Target> getTargetsByCategory(JSONObject params);
|
||||
|
||||
List<String> searchColumn(JSONObject params);
|
||||
|
||||
String getResult(JSONObject params);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package iet.ustb.sf.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@ -8,6 +9,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
|
||||
import iet.ustb.sf.domain.Category;
|
||||
import iet.ustb.sf.domain.Target;
|
||||
import iet.ustb.sf.domain.TargetOption;
|
||||
import iet.ustb.sf.exception.ErrorCode;
|
||||
import iet.ustb.sf.exception.ThrowUtils;
|
||||
import iet.ustb.sf.mapper.CategoryMapper;
|
||||
@ -19,6 +21,9 @@ import lombok.val;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -80,6 +85,154 @@ public class TargetServiceImpl extends ServiceImpl<TargetMapper, Target>
|
||||
List<Map<String, Object>> list = SqlRunner.db().selectList(sql);
|
||||
return list.stream().map(target -> target.get(columnName).toString()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResult(JSONObject params) {
|
||||
String sql = getResultSql(params);
|
||||
List<Map<String, Object>> list = SqlRunner.db().selectList(sql);
|
||||
TargetOption result = params.getJSONObject("result").toJavaObject(TargetOption.class);
|
||||
return list.get(0).get(result.getColumnName()).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接结果sql
|
||||
*
|
||||
* @param params 传入参数
|
||||
* @return 结果sql
|
||||
*/
|
||||
private String getResultSql(JSONObject params) {
|
||||
String tableName = params.getString("tableName");
|
||||
CheckUtils.checkTableName(tableName);
|
||||
List<TargetOption> searchList = params.getJSONArray("search").toJavaList(TargetOption.class);
|
||||
CheckUtils.checkSearchOption(searchList, tableName);
|
||||
TargetOption result = params.getJSONObject("result").toJavaObject(TargetOption.class);
|
||||
CheckUtils.checkResultOption(result, tableName);
|
||||
return "SELECT ROUND(" + result.getFun() + "(CAST(" + result.getColumnName() + " AS DOUBLE)), 6) AS " +
|
||||
result.getColumnName() + " FROM " + tableName + " WHERE " + getWhereSql(searchList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接条件sql
|
||||
*
|
||||
* @param searchList 条件列表
|
||||
* @return 条件sql
|
||||
*/
|
||||
private String getWhereSql(List<TargetOption> searchList) {
|
||||
StringBuilder sql = new StringBuilder();
|
||||
for (TargetOption option : searchList) {
|
||||
int type = option.getType();
|
||||
if (type == 1) {
|
||||
String start, end;
|
||||
LocalDate day = LocalDate.now();
|
||||
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
switch (option.getFun()) {
|
||||
case "yesterday":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(1).format(dtf);
|
||||
break;
|
||||
case "week":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(1).with(DayOfWeek.MONDAY).format(dtf);
|
||||
break;
|
||||
case "lastWeek":
|
||||
day = day.minusDays(1).with(DayOfWeek.MONDAY);
|
||||
start = day.minusDays(7).format(dtf);
|
||||
end = day.format(dtf);
|
||||
break;
|
||||
case "nearlyWeek":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(7).format(dtf);
|
||||
break;
|
||||
case "month":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(1).withDayOfMonth(1).format(dtf);
|
||||
break;
|
||||
case "lastMonth":
|
||||
day = day.withDayOfMonth(1);
|
||||
end = day.format(dtf);
|
||||
start = day.minusMonths(1).format(dtf);
|
||||
break;
|
||||
case "nearlyMonth":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(30).format(dtf);
|
||||
break;
|
||||
case "product":
|
||||
end = day.format(dtf);
|
||||
day = day.minusDays(1);
|
||||
if (day.getDayOfMonth() < 26) {
|
||||
start = day.minusMonths(1).withDayOfMonth(26).format(dtf);
|
||||
} else {
|
||||
start = day.withDayOfMonth(26).format(dtf);
|
||||
}
|
||||
break;
|
||||
case "lastProduct":
|
||||
day = day.minusDays(1);
|
||||
if (day.getDayOfMonth() < 26) {
|
||||
day = day.minusMonths(1).withDayOfMonth(26);
|
||||
} else {
|
||||
day = day.withDayOfMonth(26);
|
||||
}
|
||||
end = day.format(dtf);
|
||||
start = day.minusMonths(1).format(dtf);
|
||||
break;
|
||||
default:
|
||||
start = "";
|
||||
end = "";
|
||||
break;
|
||||
}
|
||||
sql.append(option.getColumnName()).append(" >= '").append(start).append("' and ")
|
||||
.append(option.getColumnName()).append(" < '").append(end).append("' and ");
|
||||
} else if (type == 2) {
|
||||
sql.append(getIsNullSql(option));
|
||||
} else {
|
||||
sql.append("CAST(").append(option.getColumnName()).append(" AS DOUBLE)");
|
||||
if ("between".equals(option.getFun())) {
|
||||
double[] vals = Arrays.stream(option.getVal().split(",")).mapToDouble(Double::parseDouble).toArray();
|
||||
sql.append(("between ")).append(vals[0]).append(" and ").append(vals[1]).append(" ");
|
||||
} else {
|
||||
sql.append(option.getFun()).append(" ").append(option.getVal()).append(" ");
|
||||
}
|
||||
sql.append("and ");
|
||||
}
|
||||
}
|
||||
sql = new StringBuilder(sql.substring(0, sql.length() - 4));
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理条件中可能包含NULL的情况
|
||||
*
|
||||
* @param option 单个条件
|
||||
* @return 结果
|
||||
*/
|
||||
private String getIsNullSql(TargetOption option) {
|
||||
boolean isNull = false;
|
||||
StringBuilder tmpSql = new StringBuilder();
|
||||
if (StringUtils.isEmpty(option.getVal())) {
|
||||
return "( " + option.getColumnName() + " IS NULL OR " + option.getColumnName() + "='' ) AND ";
|
||||
}
|
||||
if (option.getVal().startsWith(",") || option.getVal().endsWith(",")) {
|
||||
isNull = true;
|
||||
}
|
||||
String[] vals = option.getVal().split(",");
|
||||
tmpSql.append(option.getColumnName()).append(" in(");
|
||||
for (String val : vals) {
|
||||
if (StringUtils.isEmpty(val)) {
|
||||
isNull = true;
|
||||
} else {
|
||||
tmpSql.append("'").append(val).append("',");
|
||||
}
|
||||
}
|
||||
tmpSql = new StringBuilder(tmpSql.substring(0, tmpSql.length() - 1));
|
||||
tmpSql.append(")");
|
||||
if (isNull) {
|
||||
tmpSql = new StringBuilder("(" + tmpSql + " OR "
|
||||
+ option.getColumnName() + " IS NULL OR "
|
||||
+ option.getColumnName() + " ='' )");
|
||||
}
|
||||
tmpSql.append(" and ");
|
||||
return tmpSql.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
package iet.ustb.sf.util;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
|
||||
import iet.ustb.sf.domain.TargetOption;
|
||||
import iet.ustb.sf.exception.ErrorCode;
|
||||
import iet.ustb.sf.exception.MyException;
|
||||
import iet.ustb.sf.exception.ThrowUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* CheckUtils
|
||||
@ -35,7 +38,8 @@ public class CheckUtils {
|
||||
*/
|
||||
public static void checkTableName(String tableName) {
|
||||
checkEmpty(tableName, "表名");
|
||||
String sql = "SELECT COUNT(1) FROM information_schema.tables WHERE table_schema = 'dwops_extension' AND table_name = '" + tableName + "'";
|
||||
String sql = "SELECT COUNT(1) FROM information_schema.tables " +
|
||||
"WHERE table_schema = 'dwops_extension' AND table_name = '" + tableName + "'";
|
||||
long cnt = SqlRunner.db().selectCount(sql);
|
||||
ThrowUtils.throwIf(cnt <= 0, new RuntimeException("表" + tableName + "不存在!"));
|
||||
}
|
||||
@ -51,4 +55,100 @@ public class CheckUtils {
|
||||
String sql = "SELECT " + columns + " FROM " + tableName + " limit 5";
|
||||
SqlRunner.db().selectList(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件指标验证
|
||||
*
|
||||
* @param optionList 条件指标集合
|
||||
* @param tableName 表名
|
||||
*/
|
||||
public static void checkSearchOption(List<TargetOption> optionList, String tableName) {
|
||||
String columns = optionList.stream().map(TargetOption::getColumnName).collect(Collectors.joining(","));
|
||||
checkColumns(columns, tableName);
|
||||
for (TargetOption option : optionList) {
|
||||
checkSingleOption(option);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个条件指标
|
||||
*
|
||||
* @param option 指标
|
||||
*/
|
||||
public static void checkSingleOption(TargetOption option) {
|
||||
String columns = option.getColumnName();
|
||||
checkEmpty(columns, "列名");
|
||||
List<Integer> typeList = Arrays.asList(1, 2, 3);
|
||||
ThrowUtils.throwIf(
|
||||
!typeList.contains(option.getType()),
|
||||
ErrorCode.PARAMS_ERROR,
|
||||
columns + ":指标中的类型不对!"
|
||||
);
|
||||
List<String> funList;
|
||||
switch (option.getType()) {
|
||||
case 1:
|
||||
ThrowUtils.throwIf(
|
||||
StringUtils.isEmpty(option.getFun()),
|
||||
ErrorCode.PARAMS_ERROR,
|
||||
columns + ":日期类型的指标,日期选项不能为空!"
|
||||
);
|
||||
funList = Arrays.asList("yesterday", "week", "nearlyWeek", "lastWeek", "month", "lastMonth",
|
||||
"nearlyMonth", "product", "lastProduct");
|
||||
ThrowUtils.throwIf(
|
||||
!funList.contains(option.getFun()),
|
||||
ErrorCode.PARAMS_ERROR,
|
||||
columns + ":日期类型的指标,日期选项不对!"
|
||||
);
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
ThrowUtils.throwIf(
|
||||
StringUtils.isEmpty(option.getFun()),
|
||||
ErrorCode.PARAMS_ERROR,
|
||||
columns + ":数值类型的指标,符号不能为空!"
|
||||
);
|
||||
funList = Arrays.asList(">", ">=", "<", "<=", "=", "!=", "between");
|
||||
ThrowUtils.throwIf(
|
||||
!funList.contains(option.getFun()),
|
||||
ErrorCode.PARAMS_ERROR,
|
||||
columns + ":数值类型的指标,符号不对!"
|
||||
);
|
||||
ThrowUtils.throwIf(
|
||||
StringUtils.isEmpty(option.getVal()),
|
||||
ErrorCode.PARAMS_ERROR,
|
||||
columns + ":数值类型的指标,值不能为空!"
|
||||
);
|
||||
if ("between".equals(option.getFun())) {
|
||||
String[] nums = option.getVal().split(",");
|
||||
ThrowUtils.throwIf(
|
||||
nums.length != 2,
|
||||
ErrorCode.PARAMS_ERROR,
|
||||
columns + "范围条件请输入两个数值!"
|
||||
);
|
||||
try {
|
||||
if (Double.parseDouble(nums[0]) > Double.parseDouble(nums[1])) {
|
||||
throw new MyException(ErrorCode.PARAMS_ERROR, columns + ":范围条件请确保前面的值小于等于后面的值!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MyException(ErrorCode.PARAMS_ERROR, columns + ":请传入两个数值!");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 结果指标验证
|
||||
*
|
||||
* @param option 结果指标
|
||||
* @param tableName 表名
|
||||
*/
|
||||
public static void checkResultOption(TargetOption option, String tableName) {
|
||||
String fun = option.getFun();
|
||||
checkEmpty(fun, "函数");
|
||||
List<String> funList = Arrays.asList("SUM", "AVG", "MAX", "MIN", "MEDIAN", "COUNT");
|
||||
ThrowUtils.throwIf(!funList.contains(fun), ErrorCode.PARAMS_ERROR, "方法错误!");
|
||||
checkColumns(option.getColumnName(), tableName);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user