|
|
<?xml version="1.0" encoding="UTF-8" ?>
|
|
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
|
<mapper namespace="org.dromara.ems.report.mapper.TempBoardMapper">
|
|
|
|
|
|
<!-- 公共字段片段:每个分表 SELECT 温度相关字段 + JOIN 测点名称 -->
|
|
|
<sql id="baseColumns">
|
|
|
t.monitorId,
|
|
|
t.temperature,
|
|
|
t.collectTime,
|
|
|
t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
</sql>
|
|
|
|
|
|
<!-- 公共 JOIN:关联测点主信息表获取 monitor_name 和 monitor_type -->
|
|
|
<sql id="baseJoin">
|
|
|
LEFT JOIN ems_base_monitor_info ebmi ON t.monitorId = ebmi.monitor_code
|
|
|
</sql>
|
|
|
|
|
|
<!-- 公共过滤:温度类型设备(type=5 温度, type=6 温湿度),且温度 > 0 -->
|
|
|
<sql id="tempFilter">
|
|
|
AND (ebmi.monitor_type IN (5, 6) OR ebmi.monitor_type IS NULL)
|
|
|
AND (t.temperature IS NULL OR (t.temperature BETWEEN 0 AND 79))
|
|
|
AND (
|
|
|
(ebmi.monitor_type = 5 AND t.temperature > 0) OR
|
|
|
(ebmi.monitor_type = 6 AND t.temperature > 0) OR
|
|
|
(ebmi.monitor_type NOT IN (5, 6) OR ebmi.monitor_type IS NULL)
|
|
|
)
|
|
|
</sql>
|
|
|
|
|
|
<!-- 公共时间过滤 -->
|
|
|
<sql id="timeFilter">
|
|
|
AND t.collectTime >= #{startTime}
|
|
|
AND t.collectTime < #{endTime}
|
|
|
</sql>
|
|
|
|
|
|
<!-- ==================== A. 温度总览 ==================== -->
|
|
|
|
|
|
<!-- A1. 活跃测点数 -->
|
|
|
<select id="countDistinctMonitors" resultType="int">
|
|
|
SELECT COUNT(DISTINCT sub.monitorId)
|
|
|
FROM (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
) sub
|
|
|
</select>
|
|
|
|
|
|
<!-- A2. 最新平均温度(CTE + ROW_NUMBER 取每个测点最新一条) -->
|
|
|
<select id="selectLatestAvgTemp" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardOverviewVo">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT ROUND(AVG(temperature), 2) AS avgLatestTemp
|
|
|
FROM latest WHERE rn = 1
|
|
|
</select>
|
|
|
|
|
|
<!-- A3. 最新最高/最低温度(先取每个测点最新值,再用独立 CTE 算极值,避免聚合函数嵌套子查询) -->
|
|
|
<select id="selectLatestMinMaxTemp" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardOverviewVo">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
),
|
|
|
latest_only AS (
|
|
|
SELECT monitorId, temperature, monitorName
|
|
|
FROM latest WHERE rn = 1
|
|
|
),
|
|
|
max_val AS (
|
|
|
SELECT TOP 1 monitorId AS maxTempMonitorId, temperature AS maxLatestTemp
|
|
|
FROM latest_only ORDER BY temperature DESC
|
|
|
),
|
|
|
min_val AS (
|
|
|
SELECT TOP 1 monitorId AS minTempMonitorId, temperature AS minLatestTemp
|
|
|
FROM latest_only ORDER BY temperature ASC
|
|
|
)
|
|
|
SELECT m.maxTempMonitorId, m.maxLatestTemp,
|
|
|
n.minTempMonitorId, n.minLatestTemp
|
|
|
FROM max_val m CROSS JOIN min_val n
|
|
|
</select>
|
|
|
|
|
|
<!-- A4. 高温 TopN -->
|
|
|
<select id="selectHighTempTopN" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardOverviewVo$MonitorTempRank">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT TOP (#{topN}) monitorId, monitorName, temperature, collectTime
|
|
|
FROM latest WHERE rn = 1
|
|
|
ORDER BY temperature DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- A5. 低温 TopN -->
|
|
|
<select id="selectLowTempTopN" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardOverviewVo$MonitorTempRank">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT TOP (#{topN}) monitorId, monitorName, temperature, collectTime
|
|
|
FROM latest WHERE rn = 1
|
|
|
ORDER BY temperature ASC
|
|
|
</select>
|
|
|
|
|
|
<!-- A6. 数据新鲜度概览 -->
|
|
|
<select id="selectFreshnessList" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardOverviewVo$FreshnessItem">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT monitorId, monitorName, temperature, collectTime,
|
|
|
DATEDIFF(SECOND, collectTime, GETUTCDATE()) AS ageSeconds
|
|
|
FROM latest WHERE rn = 1
|
|
|
ORDER BY ageSeconds DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- ==================== B. 实时监控 ==================== -->
|
|
|
|
|
|
<!-- B1. 实时温度明细(含延迟) -->
|
|
|
<select id="selectRealtimeDetail" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardRealtimeVo">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, recodeTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT monitorId, monitorName, temperature, collectTime, recodeTime,
|
|
|
DATEDIFF(SECOND, collectTime, recodeTime) AS delaySeconds,
|
|
|
DATEDIFF(SECOND, collectTime, GETUTCDATE()) AS staleSeconds
|
|
|
FROM latest WHERE rn = 1
|
|
|
ORDER BY collectTime DESC, monitorId
|
|
|
</select>
|
|
|
|
|
|
<!-- B2. 高温测点 -->
|
|
|
<select id="selectHighTempMonitors" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardRealtimeVo">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, recodeTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT monitorId, monitorName, temperature, collectTime, recodeTime,
|
|
|
DATEDIFF(SECOND, collectTime, recodeTime) AS delaySeconds
|
|
|
FROM latest WHERE rn = 1 AND temperature >= #{highTempThreshold}
|
|
|
ORDER BY temperature DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- B3. 低温测点 -->
|
|
|
<select id="selectLowTempMonitors" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardRealtimeVo">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, recodeTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT monitorId, monitorName, temperature, collectTime, recodeTime,
|
|
|
DATEDIFF(SECOND, collectTime, recodeTime) AS delaySeconds
|
|
|
FROM latest WHERE rn = 1 AND temperature <= #{lowTempThreshold}
|
|
|
ORDER BY temperature ASC
|
|
|
</select>
|
|
|
|
|
|
<!-- B4. 长时间未更新测点 -->
|
|
|
<select id="selectStaleMonitors" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardRealtimeVo">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, recodeTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT monitorId, monitorName, temperature, collectTime,
|
|
|
DATEDIFF(SECOND, collectTime, GETUTCDATE()) AS staleSeconds
|
|
|
FROM latest WHERE rn = 1
|
|
|
AND DATEDIFF(SECOND, collectTime, GETUTCDATE()) >= #{staleThreshold}
|
|
|
ORDER BY staleSeconds DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- B5. 入库延迟排行 -->
|
|
|
<select id="selectDelayRanking" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardRealtimeVo">
|
|
|
WITH all_data AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime, t.recodeTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
latest AS (
|
|
|
SELECT monitorId, temperature, collectTime, recodeTime, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime DESC, recodeTime DESC) AS rn
|
|
|
FROM all_data
|
|
|
)
|
|
|
SELECT monitorId, monitorName, collectTime, recodeTime,
|
|
|
DATEDIFF(SECOND, collectTime, recodeTime) AS delaySeconds
|
|
|
FROM latest WHERE rn = 1
|
|
|
ORDER BY delaySeconds DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- ==================== C. 趋势分析 ==================== -->
|
|
|
|
|
|
<!-- C1. 单测点分钟趋势 -->
|
|
|
<select id="selectMinuteTrend" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardTrendVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
FORMAT(t.collectTime, 'yyyy-MM-dd HH:mm:00') AS statTime,
|
|
|
t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp,
|
|
|
COUNT(*) AS sampleCount
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
t.monitorId = #{monitorId}
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY FORMAT(t.collectTime, 'yyyy-MM-dd HH:mm:00'), t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY statTime
|
|
|
</select>
|
|
|
|
|
|
<!-- C2. 单测点小时趋势 -->
|
|
|
<select id="selectHourlyTrend" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardTrendVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
FORMAT(t.collectTime, 'yyyy-MM-dd HH:00:00') AS statTime,
|
|
|
t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp,
|
|
|
ROUND(MAX(t.temperature), 2) AS maxTemp,
|
|
|
ROUND(MIN(t.temperature), 2) AS minTemp,
|
|
|
COUNT(*) AS sampleCount
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
t.monitorId = #{monitorId}
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY FORMAT(t.collectTime, 'yyyy-MM-dd HH:00:00'), t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY statTime
|
|
|
</select>
|
|
|
|
|
|
<!-- C3. 多测点对比趋势 -->
|
|
|
<select id="selectMultiCompareTrend" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardTrendVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
FORMAT(t.collectTime, 'yyyy-MM-dd HH:mm:00') AS statTime,
|
|
|
t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<if test="monitorIds != null and monitorIds.size() > 0">
|
|
|
AND t.monitorId IN
|
|
|
<foreach collection="monitorIds" item="mid" open="(" separator="," close=")">
|
|
|
#{mid}
|
|
|
</foreach>
|
|
|
</if>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY FORMAT(t.collectTime, 'yyyy-MM-dd HH:mm:00'), t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY statTime, monitorId
|
|
|
</select>
|
|
|
|
|
|
<!-- C4. 日均温趋势 -->
|
|
|
<select id="selectDailyTrend" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardTrendVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
FORMAT(CAST(t.collectTime AS DATE), 'yyyy-MM-dd') AS statTime,
|
|
|
NULL AS monitorId,
|
|
|
NULL AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp,
|
|
|
ROUND(MAX(t.temperature), 2) AS maxTemp,
|
|
|
ROUND(MIN(t.temperature), 2) AS minTemp,
|
|
|
COUNT(*) AS sampleCount
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY CAST(t.collectTime AS DATE)
|
|
|
</foreach>
|
|
|
ORDER BY statTime
|
|
|
</select>
|
|
|
|
|
|
<!-- C5. 温度变化率趋势 -->
|
|
|
<select id="selectChangeRateTrend" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardTrendVo">
|
|
|
WITH base AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<if test="monitorId != null and monitorId != ''">
|
|
|
AND t.monitorId = #{monitorId}
|
|
|
</if>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
seq AS (
|
|
|
SELECT monitorId, collectTime, temperature,
|
|
|
LAG(collectTime) OVER (PARTITION BY monitorId ORDER BY collectTime) AS prevTime,
|
|
|
LAG(temperature) OVER (PARTITION BY monitorId ORDER BY collectTime) AS prevTemp
|
|
|
FROM base
|
|
|
)
|
|
|
SELECT monitorId,
|
|
|
collectTime AS statTime,
|
|
|
prevTime,
|
|
|
prevTemp,
|
|
|
temperature,
|
|
|
ROUND(
|
|
|
CAST(temperature - prevTemp AS FLOAT) /
|
|
|
NULLIF(CAST(DATEDIFF(SECOND, prevTime, collectTime) AS FLOAT), 0) * 60,
|
|
|
4
|
|
|
) AS changeRate
|
|
|
FROM seq WHERE prevTime IS NOT NULL
|
|
|
ORDER BY collectTime
|
|
|
</select>
|
|
|
|
|
|
<!-- C6. 峰谷时刻表 -->
|
|
|
<select id="selectPeakValley" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardTrendVo">
|
|
|
WITH base AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
ranked AS (
|
|
|
SELECT monitorId, collectTime, temperature, monitorName,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY temperature DESC, collectTime ASC) AS rnMax,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY temperature ASC, collectTime ASC) AS rnMin
|
|
|
FROM base
|
|
|
)
|
|
|
SELECT monitorId, monitorName,
|
|
|
MAX(CASE WHEN rnMax = 1 THEN temperature END) AS peakTemp,
|
|
|
MAX(CASE WHEN rnMax = 1 THEN collectTime END) AS peakTime,
|
|
|
MAX(CASE WHEN rnMin = 1 THEN temperature END) AS valleyTemp,
|
|
|
MAX(CASE WHEN rnMin = 1 THEN collectTime END) AS valleyTime
|
|
|
FROM ranked
|
|
|
GROUP BY monitorId, monitorName
|
|
|
</select>
|
|
|
|
|
|
<!-- ==================== D. 分布分析 ==================== -->
|
|
|
|
|
|
<!-- D1. 温度区间分布 -->
|
|
|
<select id="selectIntervalDistribution" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardDistributionVo">
|
|
|
SELECT sub.tempBucket, COUNT(*) AS sampleCount
|
|
|
FROM (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.temperature,
|
|
|
CASE
|
|
|
WHEN t.temperature < 15 THEN '<15'
|
|
|
WHEN t.temperature < 20 THEN '15-20'
|
|
|
WHEN t.temperature < 25 THEN '20-25'
|
|
|
WHEN t.temperature < 30 THEN '25-30'
|
|
|
ELSE '>=30'
|
|
|
END AS tempBucket
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
) sub
|
|
|
GROUP BY sub.tempBucket
|
|
|
ORDER BY sub.tempBucket
|
|
|
</select>
|
|
|
|
|
|
<!-- D2. 温度直方图(1℃分箱) -->
|
|
|
<select id="selectHistogram" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardDistributionVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT FLOOR(t.temperature) AS tempBin, COUNT(*) AS sampleCount
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY FLOOR(t.temperature)
|
|
|
</foreach>
|
|
|
ORDER BY tempBin
|
|
|
</select>
|
|
|
|
|
|
<!-- D3. 温度箱线图原始数据(按测点) -->
|
|
|
<select id="selectBoxplotData" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardDistributionVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
t.temperature
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
ORDER BY monitorId, temperature
|
|
|
</select>
|
|
|
|
|
|
<!-- D4. 日历热力图 -->
|
|
|
<select id="selectCalendarHeatmap" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardDistributionVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
FORMAT(CAST(t.collectTime AS DATE), 'yyyy-MM-dd') AS statDate,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY CAST(t.collectTime AS DATE)
|
|
|
</foreach>
|
|
|
ORDER BY statDate
|
|
|
</select>
|
|
|
|
|
|
<!-- D5. 小时热力图 -->
|
|
|
<select id="selectHourlyHeatmap" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardDistributionVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
FORMAT(CAST(t.collectTime AS DATE), 'yyyy-MM-dd') AS statDate,
|
|
|
DATEPART(HOUR, t.collectTime) AS statHour,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY CAST(t.collectTime AS DATE), DATEPART(HOUR, t.collectTime)
|
|
|
</foreach>
|
|
|
ORDER BY statDate, statHour
|
|
|
</select>
|
|
|
|
|
|
<!-- ==================== E. 异常预警 ==================== -->
|
|
|
|
|
|
<!-- E1. 高温事件 -->
|
|
|
<select id="selectHighTempEvents" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAnomalyVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
t.temperature,
|
|
|
t.collectTime,
|
|
|
'HIGH_TEMP' AS anomalyType
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
t.temperature >= #{highTempThreshold}
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
ORDER BY collectTime DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- E2. 低温事件 -->
|
|
|
<select id="selectLowTempEvents" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAnomalyVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
t.temperature,
|
|
|
t.collectTime,
|
|
|
'LOW_TEMP' AS anomalyType
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
t.temperature <= #{lowTempThreshold}
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
ORDER BY collectTime DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- E3. 连续高温时段(岛屿分组) -->
|
|
|
<select id="selectContinuousHighTemp" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAnomalyVo">
|
|
|
WITH base AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
flagged AS (
|
|
|
SELECT monitorId, temperature, collectTime, monitorName,
|
|
|
CASE WHEN temperature >= #{highTempThreshold} THEN 1 ELSE 0 END AS isHigh
|
|
|
FROM base
|
|
|
),
|
|
|
grouped AS (
|
|
|
SELECT *,
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId ORDER BY collectTime) -
|
|
|
ROW_NUMBER() OVER (PARTITION BY monitorId, isHigh ORDER BY collectTime) AS grp
|
|
|
FROM flagged
|
|
|
)
|
|
|
SELECT monitorId, monitorName,
|
|
|
MIN(collectTime) AS startTime,
|
|
|
MAX(collectTime) AS endTime,
|
|
|
MAX(temperature) AS maxTemp,
|
|
|
COUNT(*) AS sampleCount
|
|
|
FROM grouped WHERE isHigh = 1
|
|
|
GROUP BY monitorId, monitorName, grp
|
|
|
HAVING COUNT(*) >= 2
|
|
|
ORDER BY monitorId, startTime
|
|
|
</select>
|
|
|
|
|
|
<!-- E4. 温升过快事件 -->
|
|
|
<select id="selectRapidRiseEvents" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAnomalyVo">
|
|
|
WITH base AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.temperature, t.collectTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
seq AS (
|
|
|
SELECT monitorId, collectTime, temperature, monitorName,
|
|
|
LAG(collectTime) OVER (PARTITION BY monitorId ORDER BY collectTime) AS prevTime,
|
|
|
LAG(temperature) OVER (PARTITION BY monitorId ORDER BY collectTime) AS prevTemp
|
|
|
FROM base
|
|
|
)
|
|
|
SELECT monitorId, monitorName, collectTime, prevTime,
|
|
|
prevTemp AS prevTemp,
|
|
|
temperature,
|
|
|
ROUND(
|
|
|
CAST(temperature - prevTemp AS FLOAT) /
|
|
|
NULLIF(CAST(DATEDIFF(SECOND, prevTime, collectTime) AS FLOAT), 0) * 60,
|
|
|
4
|
|
|
) AS risePerMin
|
|
|
FROM seq WHERE prevTime IS NOT NULL
|
|
|
AND CAST(temperature - prevTemp AS FLOAT) /
|
|
|
NULLIF(CAST(DATEDIFF(SECOND, prevTime, collectTime) AS FLOAT), 0) * 60 >= #{rapidRiseThreshold}
|
|
|
ORDER BY risePerMin DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- E5. 温度抖动异常(按小时标准差) -->
|
|
|
<select id="selectJitterAnomalies" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAnomalyVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
FORMAT(t.collectTime, 'yyyy-MM-dd HH:00:00') AS statTime,
|
|
|
ROUND(STDEVP(t.temperature), 4) AS tempStddev,
|
|
|
'JITTER' AS anomalyType
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId),
|
|
|
FORMAT(t.collectTime, 'yyyy-MM-dd HH:00:00')
|
|
|
HAVING STDEVP(t.temperature) >= #{stddevThreshold}
|
|
|
</foreach>
|
|
|
ORDER BY tempStddev DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- ==================== F. 对比分析 ==================== -->
|
|
|
|
|
|
<!-- F1. 测点平均温度排行 -->
|
|
|
<select id="selectAvgTempRanking" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardComparisonVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY avgTemp DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- F2. 测点稳定性排行(标准差升序) -->
|
|
|
<select id="selectStabilityRanking" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardComparisonVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(STDEVP(t.temperature), 4) AS tempStddev
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY tempStddev ASC
|
|
|
</select>
|
|
|
|
|
|
<!-- F3. 今日vs昨日对比(拆分为 today / yesterday 两个 CTE,避免 GROUP BY 引用 collectTime 列) -->
|
|
|
<select id="selectDailyDiff" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardComparisonVo">
|
|
|
WITH today_avg AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
AVG(t.temperature) AS avgTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
t.collectTime >= #{todayStartTime} AND t.collectTime < #{todayEndTime}
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
),
|
|
|
yesterday_avg AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
AVG(t.temperature) AS avgTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
t.collectTime >= #{yesterdayStartTime} AND t.collectTime < #{yesterdayEndTime}
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
)
|
|
|
SELECT t.monitorId, t.monitorName,
|
|
|
ROUND(t.avgTemp, 2) AS todayAvg,
|
|
|
ROUND(y.avgTemp, 2) AS yesterdayAvg,
|
|
|
ROUND(t.avgTemp - y.avgTemp, 2) AS diffValue
|
|
|
FROM today_avg t
|
|
|
LEFT JOIN yesterday_avg y ON t.monitorId = y.monitorId
|
|
|
ORDER BY diffValue DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- F4. 峰值对比 -->
|
|
|
<select id="selectPeakCompare" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardComparisonVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
MAX(t.temperature) AS maxTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY maxTemp DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- F5. 波动幅度对比 -->
|
|
|
<select id="selectFluctuationCompare" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardComparisonVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
MAX(t.temperature) - MIN(t.temperature) AS tempRange
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY tempRange DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- ==================== G. 数据质量 ==================== -->
|
|
|
|
|
|
<!-- G1. 入库延迟分布 -->
|
|
|
<select id="selectDelayDistribution" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardQualityVo">
|
|
|
SELECT sub.delayBucket, COUNT(*) AS sampleCount
|
|
|
FROM (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.collectTime, t.recodeTime,
|
|
|
CASE
|
|
|
WHEN DATEDIFF(SECOND, t.collectTime, t.recodeTime) < 10 THEN '<10s'
|
|
|
WHEN DATEDIFF(SECOND, t.collectTime, t.recodeTime) < 30 THEN '10-30s'
|
|
|
WHEN DATEDIFF(SECOND, t.collectTime, t.recodeTime) < 60 THEN '30-60s'
|
|
|
ELSE '>=60s'
|
|
|
END AS delayBucket
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
) sub
|
|
|
GROUP BY sub.delayBucket
|
|
|
ORDER BY sub.delayBucket
|
|
|
</select>
|
|
|
|
|
|
<!-- G2. 时间逆序可疑数据(recodeTime < collectTime) -->
|
|
|
<select id="selectTimeReversal" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardQualityVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
t.temperature,
|
|
|
t.collectTime,
|
|
|
t.recodeTime,
|
|
|
DATEDIFF(SECOND, t.collectTime, t.recodeTime) AS delaySeconds
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
t.recodeTime < t.collectTime
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
ORDER BY collectTime DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- G3. 采样间隔异常 -->
|
|
|
<select id="selectSamplingGapAnomalies" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardQualityVo">
|
|
|
WITH base AS (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId, t.collectTime,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
),
|
|
|
seq AS (
|
|
|
SELECT monitorId, collectTime, monitorName,
|
|
|
LAG(collectTime) OVER (PARTITION BY monitorId ORDER BY collectTime) AS prevTime
|
|
|
FROM base
|
|
|
)
|
|
|
SELECT monitorId, monitorName, prevTime, collectTime,
|
|
|
DATEDIFF(SECOND, prevTime, collectTime) AS gapSeconds
|
|
|
FROM seq WHERE prevTime IS NOT NULL
|
|
|
AND DATEDIFF(SECOND, prevTime, collectTime) >= #{gapThreshold}
|
|
|
ORDER BY gapSeconds DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- G4. 数据完整率 -->
|
|
|
<select id="selectCompletenessRate" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardQualityVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
COUNT(*) AS actualCount,
|
|
|
#{expectedCount} AS expectedCount,
|
|
|
ROUND(CAST(COUNT(*) AS FLOAT) / #{expectedCount}, 4) AS completenessRate
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY completenessRate ASC
|
|
|
</select>
|
|
|
|
|
|
<!-- G5. 测点活跃度 -->
|
|
|
<select id="selectMonitorActivity" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardQualityVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
COUNT(*) AS actualCount,
|
|
|
MIN(t.collectTime) AS firstTime,
|
|
|
MAX(t.collectTime) AS lastTime
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY actualCount DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- ==================== H. 高级分析 ==================== -->
|
|
|
|
|
|
<!-- H1. 桑基图数据(温区按时间段流转)
|
|
|
优化:每表内部先做 DISTINCT(monitorId+桶) 缩小数据量,再 UNION ALL 小结果集做全局自关联 -->
|
|
|
<select id="selectSankeyData" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAdvancedVo">
|
|
|
WITH stage AS (
|
|
|
SELECT DISTINCT monitorId, timeBucket, tempBucket FROM (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT DISTINCT t.monitorId,
|
|
|
CASE
|
|
|
WHEN DATEPART(HOUR, t.collectTime) < 6 THEN 'T1'
|
|
|
WHEN DATEPART(HOUR, t.collectTime) < 12 THEN 'T2'
|
|
|
WHEN DATEPART(HOUR, t.collectTime) < 18 THEN 'T3'
|
|
|
ELSE 'T4'
|
|
|
END AS timeBucket,
|
|
|
CASE
|
|
|
WHEN t.temperature < 15 THEN '<15'
|
|
|
WHEN t.temperature < 20 THEN '15-20'
|
|
|
WHEN t.temperature < 25 THEN '20-25'
|
|
|
ELSE '>=25'
|
|
|
END AS tempBucket
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
</foreach>
|
|
|
) raw_stage
|
|
|
),
|
|
|
flow AS (
|
|
|
SELECT
|
|
|
a.timeBucket + '_' + a.tempBucket AS fromNode,
|
|
|
b.timeBucket + '_' + b.tempBucket AS toNode,
|
|
|
COUNT(*) AS flowCount
|
|
|
FROM stage a
|
|
|
INNER JOIN stage b ON a.monitorId = b.monitorId
|
|
|
AND (
|
|
|
(a.timeBucket = 'T1' AND b.timeBucket = 'T2') OR
|
|
|
(a.timeBucket = 'T2' AND b.timeBucket = 'T3') OR
|
|
|
(a.timeBucket = 'T3' AND b.timeBucket = 'T4')
|
|
|
)
|
|
|
GROUP BY a.timeBucket, a.tempBucket, b.timeBucket, b.tempBucket
|
|
|
)
|
|
|
SELECT fromNode, toNode, flowCount FROM flow
|
|
|
ORDER BY fromNode, toNode
|
|
|
</select>
|
|
|
|
|
|
<!-- H2. 主题河流图数据
|
|
|
优化:GROUP BY 使用 DATEADD 时间桶(可走索引),外层 CONVERT 格式化输出(仅对聚合后小结果集);
|
|
|
支持动态粒度:MINUTE / FIFTEEN_MINUTE / HOUR -->
|
|
|
<select id="selectThemeRiverData" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAdvancedVo">
|
|
|
SELECT
|
|
|
CONVERT(VARCHAR(19), statBucket, 120) AS statTime,
|
|
|
monitorId, monitorName, avgTemp
|
|
|
FROM (
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
<choose>
|
|
|
<when test="granularity == 'HOUR'">
|
|
|
DATEADD(HOUR, DATEDIFF(HOUR, 0, t.collectTime), 0)
|
|
|
</when>
|
|
|
<when test="granularity == 'FIFTEEN_MINUTE'">
|
|
|
DATEADD(MINUTE, (DATEDIFF(MINUTE, 0, t.collectTime) / 15) * 15, 0)
|
|
|
</when>
|
|
|
<otherwise>
|
|
|
DATEADD(MINUTE, DATEDIFF(MINUTE, 0, t.collectTime), 0)
|
|
|
</otherwise>
|
|
|
</choose> AS statBucket,
|
|
|
t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY
|
|
|
<choose>
|
|
|
<when test="granularity == 'HOUR'">
|
|
|
DATEADD(HOUR, DATEDIFF(HOUR, 0, t.collectTime), 0)
|
|
|
</when>
|
|
|
<when test="granularity == 'FIFTEEN_MINUTE'">
|
|
|
DATEADD(MINUTE, (DATEDIFF(MINUTE, 0, t.collectTime) / 15) * 15, 0)
|
|
|
</when>
|
|
|
<otherwise>
|
|
|
DATEADD(MINUTE, DATEDIFF(MINUTE, 0, t.collectTime), 0)
|
|
|
</otherwise>
|
|
|
</choose>,
|
|
|
t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
) sub
|
|
|
ORDER BY statTime, monitorId
|
|
|
</select>
|
|
|
|
|
|
<!-- H3. 矩形树图数据(按测点平均温度+样本数)
|
|
|
每张日表独立聚合,UNION ALL 直接输出 -->
|
|
|
<select id="selectTreemapData" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAdvancedVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp,
|
|
|
COUNT(*) AS sampleCount
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY avgTemp DESC
|
|
|
</select>
|
|
|
|
|
|
<!-- H4. 旭日图数据(温区→测点层级)
|
|
|
每张日表独立聚合,UNION ALL 直接输出 -->
|
|
|
<select id="selectSunburstData" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAdvancedVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT
|
|
|
CASE
|
|
|
WHEN t.temperature < 15 THEN '<15'
|
|
|
WHEN t.temperature < 20 THEN '15-20'
|
|
|
WHEN t.temperature < 25 THEN '20-25'
|
|
|
WHEN t.temperature < 30 THEN '25-30'
|
|
|
ELSE '>=30'
|
|
|
END AS tempBucket,
|
|
|
t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
COUNT(*) AS sampleCount
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY
|
|
|
CASE
|
|
|
WHEN t.temperature < 15 THEN '<15'
|
|
|
WHEN t.temperature < 20 THEN '15-20'
|
|
|
WHEN t.temperature < 25 THEN '20-25'
|
|
|
WHEN t.temperature < 30 THEN '25-30'
|
|
|
ELSE '>=30'
|
|
|
END,
|
|
|
t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY tempBucket, monitorId
|
|
|
</select>
|
|
|
|
|
|
<!-- H5. 平行坐标图数据(多维温度画像)
|
|
|
每张日表独立聚合,UNION ALL 直接输出 -->
|
|
|
<select id="selectParallelData" resultType="org.dromara.ems.report.domain.vo.tempboard.TempBoardAdvancedVo">
|
|
|
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
|
|
|
SELECT t.monitorId,
|
|
|
COALESCE(ebmi.monitor_name, t.monitorId) AS monitorName,
|
|
|
ROUND(AVG(t.temperature), 2) AS avgTemp,
|
|
|
ROUND(MAX(t.temperature), 2) AS maxTemp,
|
|
|
ROUND(MIN(t.temperature), 2) AS minTemp,
|
|
|
ROUND(STDEVP(t.temperature), 4) AS tempStddev,
|
|
|
ROUND(AVG(CAST(DATEDIFF(SECOND, t.collectTime, t.recodeTime) AS FLOAT)), 2) AS avgDelay
|
|
|
FROM ${tableName} t
|
|
|
<include refid="baseJoin"/>
|
|
|
<where>
|
|
|
<include refid="timeFilter"/>
|
|
|
<include refid="tempFilter"/>
|
|
|
</where>
|
|
|
GROUP BY t.monitorId, COALESCE(ebmi.monitor_name, t.monitorId)
|
|
|
</foreach>
|
|
|
ORDER BY avgTemp DESC
|
|
|
</select>
|
|
|
|
|
|
</mapper>
|