You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SQL统计结果添加最值对应的timestamp

解决方案

1. 先新增所需字段

首先给tReportAvgMinMax表添加存储最值对应时间的字段:

ALTER TABLE tReportAvgMinMax 
ADD Timestamp_min DATETIME,
ADD Timestamp_max DATETIME;

2. 高效的插入语句(单表扫描版)

使用窗口函数ROW_NUMBER()一次性计算出每个point_id的平均值、最值及对应时间,避免多次扫描tData表导致的性能损耗:

INSERT INTO tReportAvgMinMax (Date, point_id, average, minimum, maximum, Timestamp_min, Timestamp_max)
SELECT 
    @Date,
    Def.point_id,
    agg.average,
    agg.minimum,
    agg.maximum,
    agg.Timestamp_min,
    agg.Timestamp_max
FROM tDefAvgMinMax Def
LEFT JOIN (
    SELECT 
        point_id,
        AVG(Value) AS average,
        MIN(Value) AS minimum,
        MAX(Value) AS maximum,
        -- 取最小值对应的最早时间,要最晚时间可改ORDER BY Timestamp DESC
        FIRST_VALUE(Timestamp) OVER (PARTITION BY point_id ORDER BY Value ASC, Timestamp ASC) AS Timestamp_min,
        -- 取最大值对应的最早时间,要最晚时间可改ORDER BY Timestamp DESC
        FIRST_VALUE(Timestamp) OVER (PARTITION BY point_id ORDER BY Value DESC, Timestamp ASC) AS Timestamp_max
    FROM tData
    WHERE Timestamp BETWEEN CAST(@Date AS DATETIME) + '00:00:00' AND CAST(@Date AS DATETIME) + '23:59:59'
    GROUP BY point_id, Timestamp, Value
) agg ON Def.point_id = agg.point_id;

大数据量优化版(分步聚合)

如果tData表数据量极大,可通过CTE分步聚合,减少单步计算的数据量:

WITH daily_agg AS (
    SELECT 
        point_id,
        AVG(Value) AS average,
        MIN(Value) AS minimum,
        MAX(Value) AS maximum
    FROM tData
    WHERE Timestamp BETWEEN CAST(@Date AS DATETIME) + '00:00:00' AND CAST(@Date AS DATETIME) + '23:59:59'
    GROUP BY point_id
),
min_time AS (
    SELECT 
        point_id,
        MIN(Timestamp) AS Timestamp_min -- 多值取最早,要最晚则用MAX
    FROM tData
    WHERE 
        Timestamp BETWEEN CAST(@Date AS DATETIME) + '00:00:00' AND CAST(@Date AS DATETIME) + '23:59:59'
        AND (point_id, Value) IN (SELECT point_id, minimum FROM daily_agg)
    GROUP BY point_id
),
max_time AS (
    SELECT 
        point_id,
        MIN(Timestamp) AS Timestamp_max -- 多值取最早,要最晚则用MAX
    FROM tData
    WHERE 
        Timestamp BETWEEN CAST(@Date AS DATETIME) + '00:00:00' AND CAST(@Date AS DATETIME) + '23:59:59'
        AND (point_id, Value) IN (SELECT point_id, maximum FROM daily_agg)
    GROUP BY point_id
)
INSERT INTO tReportAvgMinMax (Date, point_id, average, minimum, maximum, Timestamp_min, Timestamp_max)
SELECT 
    @Date,
    Def.point_id,
    da.average,
    da.minimum,
    da.maximum,
    mt.Timestamp_min,
    xt.Timestamp_max
FROM tDefAvgMinMax Def
LEFT JOIN daily_agg da ON Def.point_id = da.point_id
LEFT JOIN min_time mt ON Def.point_id = mt.point_id
LEFT JOIN max_time xt ON Def.point_id = xt.point_id;

关键说明

  • 两种方案都保留了原逻辑中对tDefAvgMinMax全量point_id的统计,即使当天无数据,对应字段会以NULL填充。
  • 窗口函数方案只需扫描tData一次,性能更优;分步聚合方案逻辑更直观,适合需要灵活调整时间规则的场景。
  • 若存在多个相同最值的记录,可通过调整排序规则或MIN/MAX(Timestamp)来选择取最早或最晚的时间戳。

内容的提问来源于stack exchange,提问作者Jean-Charles Trottier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 20:05:23