diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index ea68c002..85651c10 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -1,9 +1,11 @@ package com.yfd.platform.qgc_eng.eq.controller; +import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; @@ -193,4 +195,12 @@ public class EngEqDataController { public ResponseResult getMsEngKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(engEqDataService.getMsEngKendoList(dataSourceRequest)); } + + @Log(module = "生态流量监测数据管理", value = "删除生态流量小时/日/月数据") + @PostMapping("/data/removeKendoByIds") + @Operation(summary = "删除生态流量小时/日/月数据") + public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { + engEqDataService.removeKendoByIds(batchDeleteAo); + return ResponseResult.success(); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index 54caab7b..16cd71d5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -2,6 +2,7 @@ package com.yfd.platform.qgc_eng.eq.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_eng.eq.entity.vo.*; import java.util.List; @@ -76,4 +77,12 @@ public interface EngEqDataService { *

对应旧系统 EngEqController.getKendoListCust

*/ DataSourceResult getMsEngKendoList(DataSourceRequest dataSourceRequest); + + /** + * 批量删除生态流量小时/日/月数据 + *

删除小时数据后会按受影响站点重新聚合日表(SD_QECDAY_S)和月表(SD_QECDRTP_S)

+ * + * @param batchDeleteAo dataType: TIME=小时 DATE=日 MON=月;dataList: 删除数据列表 + */ + boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index b7676e03..c75d6542 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -1,6 +1,7 @@ package com.yfd.platform.qgc_eng.eq.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.common.DataSourceLoadOptionsBase; @@ -37,15 +38,26 @@ import com.yfd.platform.qgc_eng.eq.entity.vo.WbsbVo; import com.yfd.platform.qgc_eng.eq.entity.vo.StBaseInfo; import com.yfd.platform.qgc_eng.eq.entity.vo.StcdInfoVo; import com.yfd.platform.qgc_eng.eq.service.EngEqDataService; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; +import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; +import com.yfd.platform.qgc_base.entity.vo.DataParam; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.qgc_env.wq.entity.vo.MsWarnRuleDetailBVo; import com.yfd.platform.qgc_env.wt.utils.SiteAvoidanceUtils; import com.yfd.platform.utils.QgcQueryWrapperUtil; +import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -67,6 +79,39 @@ public class EngEqDataServiceImpl implements EngEqDataService { @Resource private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + @Resource + private JdbcTemplate jdbcTemplate; + + private static final String QEC_HOUR_TABLE_NAME = "SD_QEC_R"; + private static final String QEC_DAY_TABLE_NAME = "SD_QECDAY_S"; + private static final String QEC_DRTP_TABLE_NAME = "SD_QECDRTP_S"; + + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + + private static final LinkedHashMap QEC_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + QEC_FIELD_MEANING_MAP.put("QEC", "生态流量"); + QEC_FIELD_MEANING_MAP.put("WATERFLOW", "AI识别生态流量值"); + QEC_FIELD_MEANING_MAP.put("TPQEC", "生态流量泄放方式"); + QEC_FIELD_MEANING_MAP.put("SFDB", "生态流量是否达标"); + QEC_FIELD_MEANING_MAP.put("MWR_SFDB", "生态流量是否达标(水利部)"); + QEC_FIELD_MEANING_MAP.put("AVQ_SFDB", "生态流量是否达标(多年平均)"); + QEC_FIELD_MEANING_MAP.put("QEC_LIMIT", "生态流量限值(环保部)"); + QEC_FIELD_MEANING_MAP.put("MWR_LIMIT", "生态流量限值(水利部)"); + QEC_FIELD_MEANING_MAP.put("AVQ_LIMIT", "生态流量限值(多年平均)"); + QEC_FIELD_MEANING_MAP.put("QEC_C", "生态流量限值系数(环保部)"); + QEC_FIELD_MEANING_MAP.put("MWR_C", "生态流量限值系数(水利部)"); + QEC_FIELD_MEANING_MAP.put("AVQ_C", "生态流量系数(多年平均)"); + QEC_FIELD_MEANING_MAP.put("QEC_RULE_DID", "环保部生态流量告警规则详情ID"); + QEC_FIELD_MEANING_MAP.put("QEC_MWRRULE_DID", "水利部生态流量告警规则详情ID"); + QEC_FIELD_MEANING_MAP.put("SHOW_FLAG", "数据显示类型"); + } + @Override public DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -6671,4 +6716,529 @@ public class EngEqDataServiceImpl implements EngEqDataService { return "tm".equalsIgnoreCase(field); } + @Override + @Transactional(rollbackFor = Exception.class) + public boolean removeKendoByIds(BatchDeleteAo batchDeleteAo) { + List dataList = batchDeleteAo == null ? null : batchDeleteAo.getDataList(); + if (CollUtil.isEmpty(dataList)) { + return true; + } + String dataType = StrUtil.blankToDefault(batchDeleteAo.getDataType(), "").toUpperCase(); + String source = batchDeleteAo == null ? null : batchDeleteAo.getSource(); + int batchSize = 500; + for (int i = 0; i < dataList.size(); i += batchSize) { + List subList = dataList.subList(i, Math.min(i + batchSize, dataList.size())); + if ("MON".equals(dataType)) { + List> beforeRows = queryQecMonthRows(subList); + softDeleteQecDrtpData(subList); + recordQecDeleteLog(beforeRows, QEC_DRTP_TABLE_NAME, "删除生态流量月数据", source); + } + if ("DATE".equals(dataType)) { + List> beforeRows = queryQecDayRows(subList); + softDeleteQecDayData(subList); + recordQecDeleteLog(beforeRows, QEC_DAY_TABLE_NAME, "删除生态流量日数据", source); + } + if ("TIME".equals(dataType)) { + List> beforeRows = queryQecHourRows(subList); + deleteQecHourData(subList); + recordQecDeleteLog(beforeRows, QEC_HOUR_TABLE_NAME, "删除生态流量小时数据", source); + + Map dateRangeMap = new HashMap<>(); + Map monthRangeMap = new HashMap<>(); + for (DataParam param : subList) { + String stcd = param == null ? null : param.getId(); + String tm = param == null ? null : param.getTm(); + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm) || tm.length() < 10) { + continue; + } + String dateStr = tm.substring(0, 10); + dateRangeMap.compute(stcd, (key, range) -> { + if (range == null) { + return new String[]{dateStr, dateStr}; + } + if (dateStr.compareTo(range[0]) < 0) { + range[0] = dateStr; + } + if (dateStr.compareTo(range[1]) > 0) { + range[1] = dateStr; + } + return range; + }); + + String[] ym = tm.substring(0, 7).split("-"); + if (ym.length == 2) { + Integer year = Integer.parseInt(ym[0]); + Integer month = Integer.parseInt(ym[1]); + String monthStart = year + "-" + String.format("%02d", month) + "-01"; + String monthEnd = getMonthEndDate(year, month); + monthRangeMap.putIfAbsent(stcd + "_" + year + "_" + month, + new String[]{stcd, monthStart, monthEnd}); + } + } + + for (Map.Entry entry : dateRangeMap.entrySet()) { + statisticsQecDayDataFromHour(entry.getKey(), entry.getValue()[0], entry.getValue()[1]); + } + Set processedMonths = new HashSet<>(); + for (String[] values : monthRangeMap.values()) { + String monthKey = values[0] + "_" + values[1]; + if (processedMonths.add(monthKey)) { + statisticsQecMonthDataFromDay(values[0], values[1], values[2]); + } + } + } + } + return true; + } + + private void softDeleteQecDrtpData(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return; + } + StringBuilder sql = new StringBuilder("MERGE INTO SD_QECDRTP_S target USING ("); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" UNION ALL "); + } + sql.append("SELECT ? AS STCD, ? AS DRTP, ? AS YEAR, ? AS MONTH FROM DUAL"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDrtp()); + params.add(item == null ? null : item.getYear()); + params.add(item == null ? null : item.getMonth()); + } + sql.append(") source ON (target.STCD = source.STCD AND target.DRTP = source.DRTP ") + .append("AND target.YEAR = source.YEAR AND target.MONTH = source.MONTH) ") + .append("WHEN MATCHED THEN UPDATE SET target.IS_DELETED = 1, target.DELETE_TIME = SYSDATE"); + jdbcTemplate.update(sql.toString(), params.toArray()); + } + + private void softDeleteQecDayData(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return; + } + StringBuilder sql = new StringBuilder("MERGE INTO SD_QECDAY_S target USING ("); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" UNION ALL "); + } + sql.append("SELECT ? AS STCD, TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS') AS DT FROM DUAL"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDt()); + } + sql.append(") source ON (target.STCD = source.STCD AND target.DT = source.DT) ") + .append("WHEN MATCHED THEN UPDATE SET target.IS_DELETED = 1, target.DELETE_TIME = SYSDATE"); + jdbcTemplate.update(sql.toString(), params.toArray()); + } + + private void deleteQecHourData(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return; + } + StringBuilder sql = new StringBuilder("DELETE FROM SD_QEC_R WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getTm()); + } + jdbcTemplate.update(sql.toString(), params.toArray()); + } + + private void appendHourRowConditions(StringBuilder sql, List params, List dataParamList) { + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getTm()); + } + } + + private String buildQecHourLogSelectColumns() { + return "ID,STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, " + + "QEC, WATERFLOW, TPQEC, SFDB, MWR_SFDB, AVQ_SFDB, " + + "QEC_LIMIT, MWR_LIMIT, AVQ_LIMIT, QEC_C, MWR_C, AVQ_C, " + + "QEC_RULE_DID, QEC_MWRRULE_DID, SHOW_FLAG"; + } + + private String buildQecDayLogSelectColumns() { + return "ID,STCD, TO_CHAR(DT, 'YYYY-MM-DD HH24:MI:SS') AS DT, " + + "QEC, WATERFLOW, TPQEC, SFDB, MWR_SFDB, AVQ_SFDB, " + + "QEC_LIMIT, MWR_LIMIT, AVQ_LIMIT, QEC_C, MWR_C, AVQ_C, " + + "QEC_RULE_DID, QEC_MWRRULE_DID, SHOW_FLAG, IS_DELETED"; + } + + private String buildQecMonthLogSelectColumns() { + return "ID,STCD, DRTP, YEAR, MONTH, " + + "QEC, WATERFLOW, TPQEC, SFDB, MWR_SFDB, AVQ_SFDB, " + + "QEC_LIMIT, MWR_LIMIT, AVQ_LIMIT, QEC_C, MWR_C, AVQ_C, " + + "QEC_RULE_DID, QEC_MWRRULE_DID, SHOW_FLAG, IS_DELETED"; + } + + private List> queryQecHourRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildQecHourLogSelectColumns()) + .append(" FROM SD_QEC_R WHERE "); + List params = new ArrayList<>(); + appendHourRowConditions(sql, params, dataParamList); + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryQecDayRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildQecDayLogSelectColumns()) + .append(" FROM SD_QECDAY_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DT = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDt()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryQecMonthRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildQecMonthLogSelectColumns()) + .append(" FROM SD_QECDRTP_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DRTP = ? AND YEAR = ? AND MONTH = ?)"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDrtp()); + params.add(item == null ? null : item.getYear()); + params.add(item == null ? null : item.getMonth()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> normalizeLogRows(List> rows) { + List> result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + result.add(normalizeLogRow(row)); + } + return result; + } + + private Map normalizeLogRow(Map row) { + Map normalized = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return normalized; + } + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + return normalized; + } + + private void recordQecDeleteLog(List> rows, String tableName, String remark, String source) { + if (CollUtil.isEmpty(rows)) { + return; + } + List details = new ArrayList<>(); + for (Map row : rows) { + String stcd = asString(row.get("STCD")); + String recordId = asString(row.get("ID")); + MsOperationLog mainLog = buildQecMainLog(recordId, remark, source,"03"); + msOperationLogMapper.insert(mainLog); + for (Map.Entry entry : row.entrySet()) { + String fieldCode = entry.getKey(); + if (StrUtil.isBlank(fieldCode)) { + continue; + } + Object oldValue = entry.getValue(); + if (oldValue == null) { + continue; + } + details.add(buildQecDetail(mainLog.getId(), tableName, stcd, fieldCode, + oldValue, resolveQecDisplayValue(fieldCode, oldValue), + null, null, "删除字段值")); + } + } + batchInsertQecLogDetails(details); + } + + private MsOperationLog buildQecMainLog(String recordId, String remark, String source,String operationType) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveLogOperator()); + log.setOperationType(operationType); + log.setRecordId(recordId); + log.setOperateTime(new Date()); + log.setTableName(QEC_HOUR_TABLE_NAME); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildQecDetail(String mainId, + String tableName, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(tableName); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(QEC_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatLogValue(oldValueCode)); + detail.setOldValueName(formatLogValue(oldValueName)); + detail.setNewValueCode(formatLogValue(newValueCode)); + detail.setNewValueName(formatLogValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertQecLogDetails(List details) { + if (CollUtil.isEmpty(details)) { + return; + } + for (MsOperationLogDetail detail : details) { + if (detail == null) { + continue; + } + msOperationLogDetailMapper.insert(detail); + } + } + + private Object resolveQecDisplayValue(String fieldCode, Object rawValue) { + String text = formatLogValue(rawValue); + if (StrUtil.isBlank(text)) { + return rawValue; + } + return switch (fieldCode) { + case "SFDB", "MWR_SFDB", "AVQ_SFDB" -> { + Integer val = parseInteger(text); + yield val == null ? text : getQecSfdbName(val); + } + case "SHOW_FLAG" -> { + Integer val = parseInteger(text); + yield val == null ? text : getShowFlagName(val); + } + default -> text; + }; + } + + private String resolveLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + + private Integer parseInteger(Object value) { + if (value == null) { + return null; + } + try { + return Integer.parseInt(String.valueOf(value)); + } catch (NumberFormatException e) { + return null; + } + } + + private String getQecSfdbName(Integer sfdb) { + if (sfdb == null) { + return null; + } + return switch (sfdb) { + case 0 -> "不达标"; + case 1 -> "达标"; + case 2 -> "无生态流量数据"; + case 3 -> "无生态流量限值要求"; + default -> null; + }; + } + + private String getShowFlagName(Integer showFlag) { + if (showFlag == null) { + return null; + } + return switch (showFlag) { + case 1 -> "环保部"; + case 2 -> "水利部"; + case 3 -> "多年平均"; + case 4 -> "无"; + default -> null; + }; + } + + private String getMonthEndDate(Integer year, Integer month) { + Calendar calendar = Calendar.getInstance(); + calendar.set(year, month - 1, 1); + int lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); + return year + "-" + String.format("%02d", month) + "-" + String.format("%02d", lastDay); + } + + /** + * 按站点+日期范围,用小时表(SD_QEC_R)重新聚合日表(SD_QECDAY_S) + *

当天小时数据已删空时,对应日表行被清除;否则按平均值重新聚合。

+ */ + private void statisticsQecDayDataFromHour(String stcd, String startDate, String endDate) { + String deleteSql = "DELETE FROM SD_QECDAY_S T " + + "WHERE T.STCD = ? " + + "AND T.DT BETWEEN TO_DATE(?, 'YYYY-MM-DD') " + + "AND TO_DATE(?, 'YYYY-MM-DD') " + + "AND NOT EXISTS ( " + + "SELECT 1 FROM SD_QEC_R S " + + "WHERE S.STCD = T.STCD " + + "AND TRUNC(S.TM) = T.DT " + + "AND S.TM >= TO_DATE(? || ' 00:00:00', 'YYYY-MM-DD HH24:MI:SS') " + + "AND S.TM <= TO_DATE(? || ' 23:59:59', 'YYYY-MM-DD HH24:MI:SS') " + + "AND S.IS_DELETED = 0)"; + jdbcTemplate.update(deleteSql, stcd, startDate, endDate, startDate, endDate); + + String mergeSql = "MERGE INTO SD_QECDAY_S T " + + "USING ( " + + " SELECT " + + " STCD, " + + " TRUNC(TM) AS DT, " + + " AVG(QEC) AS QEC, " + + " AVG(WATERFLOW) AS WATERFLOW, " + + " MIN(SFDB) AS SFDB, " + + " MIN(MWR_SFDB) AS MWR_SFDB, " + + " MIN(AVQ_SFDB) AS AVQ_SFDB " + + " FROM SD_QEC_R " + + " WHERE STCD = ? " + + " AND TM >= TO_DATE(? || ' 00:00:00', 'YYYY-MM-DD HH24:MI:SS') " + + " AND TM <= TO_DATE(? || ' 23:59:59', 'YYYY-MM-DD HH24:MI:SS') " + + " AND IS_DELETED = 0 " + + " GROUP BY STCD, TRUNC(TM) " + + ") S " + + "ON (T.STCD = S.STCD AND T.DT = S.DT) " + + "WHEN MATCHED THEN UPDATE SET " + + " T.QEC = S.QEC, " + + " T.WATERFLOW = S.WATERFLOW, " + + " T.SFDB = S.SFDB, " + + " T.MWR_SFDB = S.MWR_SFDB, " + + " T.AVQ_SFDB = S.AVQ_SFDB, " + + " T.IS_DELETED = 0, " + + " T.DELETE_USER = NULL, " + + " T.DELETE_TIME = NULL, " + + " T.MODIFY_USER = NULL, " + + " T.MODIFY_TIME = SYSDATE " + + "WHEN NOT MATCHED THEN INSERT ( " + + " ID, STCD, DT, QEC, WATERFLOW, SFDB, MWR_SFDB, AVQ_SFDB, " + + " RECORD_TIME, IS_DELETED " + + ") VALUES ( " + + " SYS_GUID(), S.STCD, S.DT, S.QEC, S.WATERFLOW, S.SFDB, S.MWR_SFDB, S.AVQ_SFDB, " + + " SYSDATE, 0 " + + ")"; + jdbcTemplate.update(mergeSql, stcd, startDate, endDate); + } + + /** + * 按站点+月份范围,用日表(SD_QECDAY_S)重新聚合循表月数据(SD_QECDRTP_S, DRTP='MON') + *

当月日数据已删空时,对应月数据行被清除;否则按平均值重新聚合。

+ */ + private void statisticsQecMonthDataFromDay(String stcd, String startDate, String endDate) { + Integer startYearInt = Integer.parseInt(startDate.substring(0, 4)); + Integer startMonthInt = Integer.parseInt(startDate.substring(5, 7)); + Integer endMonthInt = Integer.parseInt(endDate.substring(5, 7)); + + String deleteSql = "DELETE FROM SD_QECDRTP_S T " + + "WHERE T.DRTP = 'MON' " + + "AND T.STCD = ? " + + "AND T.YEAR = ? " + + "AND T.MONTH BETWEEN ? AND ? " + + "AND NOT EXISTS ( " + + " SELECT 1 FROM SD_QECDAY_S D " + + " WHERE D.STCD = T.STCD " + + " AND D.IS_DELETED = 0 " + + " AND EXTRACT(YEAR FROM D.DT) = T.YEAR " + + " AND EXTRACT(MONTH FROM D.DT) = T.MONTH " + + " AND D.DT >= TO_DATE(?, 'YYYY-MM-DD') " + + " AND D.DT < TO_DATE(?, 'YYYY-MM-DD') + 1)"; + jdbcTemplate.update(deleteSql, stcd, startYearInt, startMonthInt, endMonthInt, startDate, endDate); + + String mergeSql = "MERGE INTO SD_QECDRTP_S T " + + "USING ( " + + " SELECT " + + " STCD, " + + " EXTRACT(YEAR FROM DT) AS YEAR, " + + " EXTRACT(MONTH FROM DT) AS MONTH, " + + " 'MON' AS DRTP, " + + " AVG(QEC) AS QEC, " + + " AVG(WATERFLOW) AS WATERFLOW, " + + " MIN(SFDB) AS SFDB, " + + " MIN(MWR_SFDB) AS MWR_SFDB, " + + " MIN(AVQ_SFDB) AS AVQ_SFDB " + + " FROM SD_QECDAY_S " + + " WHERE STCD = ? " + + " AND DT >= TO_DATE(?, 'YYYY-MM-DD') " + + " AND DT < TO_DATE(?, 'YYYY-MM-DD') + 1 " + + " AND IS_DELETED = 0 " + + " GROUP BY STCD, EXTRACT(YEAR FROM DT), EXTRACT(MONTH FROM DT) " + + ") S " + + "ON (T.STCD = S.STCD AND T.DRTP = 'MON' AND T.YEAR = S.YEAR AND T.MONTH = S.MONTH) " + + "WHEN MATCHED THEN UPDATE SET " + + " T.QEC = S.QEC, " + + " T.WATERFLOW = S.WATERFLOW, " + + " T.SFDB = S.SFDB, " + + " T.MWR_SFDB = S.MWR_SFDB, " + + " T.AVQ_SFDB = S.AVQ_SFDB, " + + " T.IS_DELETED = 0, " + + " T.DELETE_TIME = NULL, " + + " T.MODIFY_TIME = SYSDATE " + + "WHEN NOT MATCHED THEN INSERT ( " + + " ID, STCD, DRTP, YEAR, MONTH, TM, QEC, WATERFLOW, SFDB, MWR_SFDB, AVQ_SFDB, " + + " RECORD_TIME, IS_DELETED " + + ") VALUES ( " + + " SYS_GUID(), S.STCD, 'MON', S.YEAR, S.MONTH, " + + " TO_DATE(S.YEAR || '-' || S.MONTH || '-01', 'YYYY-MM-DD'), " + + " S.QEC, S.WATERFLOW, S.SFDB, S.MWR_SFDB, S.AVQ_SFDB, " + + " SYSDATE, 0 " + + ")"; + jdbcTemplate.update(mergeSql, stcd, startDate, endDate); + } + }