Browse Source

最大值最小值

master
review512jwy@163.com 3 months ago
parent
commit
fa09b4ef55
  1. 93
      src/main/java/com/dashboard/aws/lambda/service/MeasureAverageService.java

93
src/main/java/com/dashboard/aws/lambda/service/MeasureAverageService.java

@ -48,47 +48,58 @@ public class MeasureAverageService {
// 3: 查询上一小时的聚合结果(用于回退) // 3: 查询上一小时的聚合结果(用于回退)
LocalDateTime prevHour = start.minusHours(1); LocalDateTime prevHour = start.minusHours(1);
Map<String, Double> prevHourData = queryPrevHourAggregates(conn, schema, targetTable, prevHour); Map<String, AggregateResult> prevHourData = queryPrevHourAggregates(conn, schema, targetTable, prevHour);
// 4: 计算当前小时平均值(如果有) // 4: 计算当前小时平均、最大、最小
Map<String, Double> resultMap = new HashMap<>(); Map<String, AggregateResult> resultMap = new HashMap<>();
for (Map.Entry<String, List<Record>> entry : currentHourData.entrySet()) { for (Map.Entry<String, List<Record>> entry : currentHourData.entrySet()) {
String deviceId = entry.getKey(); String deviceId = entry.getKey();
double avg = computeTimeWeightedAverage(entry.getValue(), startTs, endTs); List<Record> records = entry.getValue();
resultMap.put(deviceId, avg);
double avg = computeTimeWeightedAverage(records, startTs, endTs);
double max = computeMaxValue(records);
double min = computeMinValue(records);
resultMap.put(deviceId, new AggregateResult(avg, max, min));
} }
// 5: 对比集合 A,确保所有设备都有值(否则用上一小时或 0) // 5: 对比集合 A,确保所有设备都有值(否则用上一小时或 0)
for (String deviceId : deviceSet) { for (String deviceId : deviceSet) {
if (!resultMap.containsKey(deviceId)) { if (!resultMap.containsKey(deviceId)) {
Double prevVal = prevHourData.get(deviceId); AggregateResult prev = prevHourData.get(deviceId);
double value = (prevVal != null) ? prevVal : 0.0; if (prev != null) {
resultMap.put(deviceId, value); resultMap.put(deviceId, prev);
} else {
resultMap.put(deviceId, new AggregateResult(0.0, 0.0, 0.0));
}
} }
} }
// 6: 写入本小时聚合表 // 6: 写入本小时聚合表
String insertSql = String.format( String insertSql = String.format(
"INSERT INTO %s.%s (device_id, average_value, date_year, date_month, date_day, date_hour, " + "INSERT INTO %s.%s (device_id, average_value, max_value, min_value, " +
"time_start, time_end, aggregated_at) " + "date_year, date_month, date_day, date_hour, time_start, time_end, aggregated_at) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", schema, targetTable "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
schema, targetTable
); );
try (PreparedStatement ps = conn.prepareStatement(insertSql)) { try (PreparedStatement ps = conn.prepareStatement(insertSql)) {
for (Map.Entry<String, Double> entry : resultMap.entrySet()) { for (Map.Entry<String, AggregateResult> entry : resultMap.entrySet()) {
String deviceId = entry.getKey(); String deviceId = entry.getKey();
double avg = entry.getValue(); AggregateResult r = entry.getValue();
LocalDateTime dt = start; LocalDateTime dt = start;
ps.setString(1, deviceId); ps.setString(1, deviceId);
ps.setString(2, String.format("%.6f", avg)); ps.setString(2, String.format("%.6f", r.avg));
ps.setInt(3, dt.getYear()); ps.setString(3, String.format("%.6f", r.max));
ps.setInt(4, dt.getMonthValue()); ps.setString(4, String.format("%.6f", r.min));
ps.setInt(5, dt.getDayOfMonth()); ps.setInt(5, dt.getYear());
ps.setInt(6, dt.getHour()); ps.setInt(6, dt.getMonthValue());
ps.setLong(7, startTs); ps.setInt(7, dt.getDayOfMonth());
ps.setLong(8, endTs); ps.setInt(8, dt.getHour());
ps.setTimestamp(9, Timestamp.valueOf(now)); ps.setLong(9, startTs);
ps.setLong(10, endTs);
ps.setTimestamp(11, Timestamp.valueOf(now));
ps.addBatch(); ps.addBatch();
} }
@ -126,10 +137,10 @@ public class MeasureAverageService {
} }
// 查询上一小时聚合结果 // 查询上一小时聚合结果
private Map<String, Double> queryPrevHourAggregates(Connection conn, String schema, String table, LocalDateTime prevHour) throws SQLException { private Map<String, AggregateResult> queryPrevHourAggregates(Connection conn, String schema, String table, LocalDateTime prevHour) throws SQLException {
Map<String, Double> map = new HashMap<>(); Map<String, AggregateResult> map = new HashMap<>();
String sql = String.format( String sql = String.format(
"SELECT device_id, average_value FROM %s.%s " + "SELECT device_id, average_value, max_value, min_value FROM %s.%s " +
"WHERE date_year = ? AND date_month = ? AND date_day = ? AND date_hour = ?", "WHERE date_year = ? AND date_month = ? AND date_day = ? AND date_hour = ?",
schema, table schema, table
); );
@ -140,12 +151,17 @@ public class MeasureAverageService {
ps.setInt(4, prevHour.getHour()); ps.setInt(4, prevHour.getHour());
ResultSet rs = ps.executeQuery(); ResultSet rs = ps.executeQuery();
while (rs.next()) { while (rs.next()) {
map.put(rs.getString("device_id"), rs.getDouble("average_value")); map.put(rs.getString("device_id"),
new AggregateResult(
rs.getDouble("average_value"),
rs.getDouble("max_value"),
rs.getDouble("min_value")));
} }
} }
return map; return map;
} }
// 时间加权平均
private double computeTimeWeightedAverage(List<Record> records, long startTs, long endTs) { private double computeTimeWeightedAverage(List<Record> records, long startTs, long endTs) {
if (records == null || records.isEmpty()) return 0.0; if (records == null || records.isEmpty()) return 0.0;
@ -156,15 +172,22 @@ public class MeasureAverageService {
Record rec = records.get(i); Record rec = records.get(i);
long nextTs = (i < records.size() - 1) ? records.get(i + 1).timestamp : endTs; long nextTs = (i < records.size() - 1) ? records.get(i + 1).timestamp : endTs;
double intervalMinutes = (nextTs - rec.timestamp) / 60000.0; // 转分钟 double intervalMinutes = (nextTs - rec.timestamp) / 60000.0; // 转分钟
logger.info("intervalMinutes: {}, rec.value: {}", intervalMinutes, rec.value);
sum += rec.value * intervalMinutes; sum += rec.value * intervalMinutes;
} }
logger.info("totalMinutes: {}, sum: {}", totalMinutes, sum);
return totalMinutes > 0 ? sum / totalMinutes : 0.0; return totalMinutes > 0 ? sum / totalMinutes : 0.0;
} }
// 最大值
private double computeMaxValue(List<Record> records) {
return records.stream().mapToDouble(r -> r.value).max().orElse(0.0);
}
// 最小值
private double computeMinValue(List<Record> records) {
return records.stream().mapToDouble(r -> r.value).min().orElse(0.0);
}
private static class Record { private static class Record {
long timestamp; long timestamp;
double value; double value;
@ -174,4 +197,16 @@ public class MeasureAverageService {
this.value = value; this.value = value;
} }
} }
}
private static class AggregateResult {
double avg;
double max;
double min;
AggregateResult(double avg, double max, double min) {
this.avg = avg;
this.max = max;
this.min = min;
}
}
}

Loading…
Cancel
Save