【问题标题】:Get Average, Max, Min , Last added value and Time获取平均值、最大值、最小值、最后附加值和时间
【发布时间】:2021-11-02 12:45:17
【问题描述】:

我有一个像这样的Parameters Log 表:

Log ID Temperature Humidity country Date
1 40 10 USA 2021-09-04 10:00:51.737
2 20 20 USA 2021-09-04 11:09:51.737
3 30 30 USA 2021-09-04 12:09:51.737

上表存储了不同国家在不同时间的温度、湿度等不同参数。我想要特定日期的此参数、最大值、最小值、上次添加值和上次添加时间的平均值。

例如:

Parameters Country Average Min Max Last value Last updated time
Temperature USA 30 20 40 30 2021-09-04 12:09:51.737
Humidity USA 20 10 30 30 2021-09-04 12:09:51.737

这就是我为Temperature 所做的:

;WITH CTE AS
(
    SELECT  
        AVG(Temperature) AVG_Temp,
        MIN(Temperature) MIN_Temp,
        MAX(Temperature) Max_Temp, 
        Country  
    FROM
        Parameters_Log 
    GROUP BY
        Country 
    WHERE 
        Country = 'USA' 
        AND CAST([date] AS date) = '2021-09-04' 
)

首先,我得到上述国家/地区的平均温度、最低温度和最高温度

SELECT TOP 1 
    c.Country, 
    c.AVG_Temp, 
    c.MIN_Temp,
    c.Max_Temp,
    [log].date,
    [log].Temperature 
FROM
    Parameters_Log [log] 
INNER JOIN
    cte c ON c.country = [log].country 
          AND 
WHERE
    [log].Country = 'USA' 
    AND cast([log].[date] AS date) = '2021-09-04'
ORDER BY 
    [log].[date] DESC

然后我使用 order by date desc 来获取最后添加的温度值和时间。最后,我将获得前 1 名并存储在一个临时表中,然后按照相同的过程处理湿度。

谁能指导我在性能方面最好的方法是什么?

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    您可以使用apply 取消透视这些值。然后使用row_number() 和聚合作为摘要:

    select country, parameter,
           avg(val), min(val), max(val),
           max(case when seqnum = 1 then val end) as last_val,
           max(date)
    from (select pl.country, pl.date, v.*,
                 row_number() over (partition by pl.country, v.parameter order by pl.date desc) as seqnum
          from parameters_log pl cross apply
               (values ('Temperature', pl.temperature), ('Humidity', pl.humidity)
               ) v(parameter, val)
         ) pl
    group by country, parameter;
    

    如果想要特定的一天,在子查询中添加where子句,如:

    where pl.date >= '2021-09-04' and pl.date < '2021-09-05'
    

    Here 是一个 dbfiddle。

    【讨论】:

    • @RahulBiswass 。 . .问题不在于日期。这是partition by中失踪的国家。
    • 感谢 Gordon Linoff 的建议。我研究了你和我建议的查询的执行计划。它真的解决了我的问题。以及我所学到的,在遍历表的子查询中,根据参数并添加行号以获取最后添加/更新的值。在外部查询中,您刚刚执行了 Max、min 和 Avg,最后一个值按行号 =1。
    【解决方案2】:

    请试试这个。最后一个值是根据最大 logid 选择的。将整个结果集应用交叉连接成 2 个副本。

    -- SQL SERVER
    SELECT CASE WHEN id = 1 THEN 'Temperature' ELSE 'Humidity' END Parameters
         , pl.country
         , CASE WHEN id = 1 THEN avg_temp ELSE avg_hum END Average
         , CASE WHEN id = 1 THEN min_temp ELSE min_hum END "Min"
         , CASE WHEN id = 1 THEN max_temp ELSE max_hum END "Max"
         , CASE WHEN id = 1 THEN pl.temparature ELSE pl.humidity END last_value
         , t.last_date "Last updated time"
    FROM Parameters_Log pl
    INNER JOIN (SELECT country
                     , MIN(temparature) min_temp
                     , MAX(temparature) max_temp
                     , AVG(temparature) avg_temp
                     , MIN(humidity) min_hum
                     , MAX(humidity) max_hum
                     , AVG(humidity) avg_hum
                     , MAX(logid) max_id
                     , MAX(tdate) last_date
                FROM Parameters_Log
                WHERE CAST(tdate AS date) = '2021-09-04'
                GROUP BY country) t
           ON pl.logid = t.max_id
    CROSS JOIN (SELECT 1 id UNION SELECT 2 id) c
    

    请查看网址https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=48e671202de62aeff8ea737ba4d1ba5a

    如果所需的输出取决于 max_date 则 ON 条件将

    ON pl.tdate = t.last_date
    

    如果所需的输出取决于最大 log_id,则 ON 条件将

     ON pl.logid = t.max_id
    

    【讨论】:

    • This relies on the "last value" having the highest ID。它应该是具有最新时间戳的那个。
    • 我解释了我的反对意见。您的“last_value”是 ID 最高的行。它应该是日期最新的行。 Here is a demonstration。请注意我如何交换插入行的 ID。 ID 应该无关紧要。
    • 我认为 logid 是主键。所以 id = 3 是在 2 之后插入的。提问者可以解释清楚。
    • 我认为加入条件对此起着至关重要的作用。如果所需的结果取决于 max_date,则使用 Date 加入,否则使用 max_id 加入。
    • @Schwern 请检查这个答案...dbfiddle.uk/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多