有没有更简洁的方法来编写这个PostgreSQL聚合窗口函数

问题描述 投票:0回答:1

我可以使用一系列 10 分钟记录作为累积值来计算某个站点自上午 9 点以来的降雨量,但是嵌套 SQL 似乎很冗长,我希望使其更加简洁,以便将来可维护。我可以使用 CTE,这可能会使其更干净一些,但想知道是否有一种方法可以通过 SUM & PARTITION BY 在一次调用中获得此结果,而不使用我当前的 CASE 方法?

以下 postgres 查询使用 10 分钟值计算自上午 9 点以来的降雨量。首先,我添加一个字段来确定这一天是上午 9 点之前还是之后 - 在这种情况下,我想将上午 9 点和零分钟作为前几天“上午 9 点以来的降雨量”值的一部分,但 9:01 之后的任何内容都应该是重点此时运行总计重置。我知道我在此示例中使用 10 分钟记录,但我确实希望精确到分钟,因为会有其他站点以分钟为单位进行报告,但此示例站点仅以 10 分钟为单位进行报告。

SELECT
    site_name,
    date_time_utc AT TIME ZONE 'Australia/Hobart' AS date_time_local,
    precip_10min,
    precip_since_9am,
    day_9am_val,
    SUM(precip_10min) OVER 
       (PARTITION BY site_name, day_9am_val ORDER BY date_time_utc) AS precip_since_9am_cal
FROM
    (
        SELECT *,
            CASE
                WHEN DATE_PART('hour', date_time_utc AT TIME ZONE 'Australia/Hobart') > 9 THEN (date_time_utc AT TIME ZONE 'Australia/Hobart')::date
                WHEN DATE_PART('hour', date_time_utc AT TIME ZONE 'Australia/Hobart') < 9 THEN ((date_time_utc AT TIME ZONE 'Australia/Hobart')::date - INTERVAL '1 day')::date
                WHEN DATE_PART('minutes', date_time_utc AT TIME ZONE 'Australia/Hobart') > 0 THEN (date_time_utc AT TIME ZONE 'Australia/Hobart')::date
                ELSE ((date_time_utc AT TIME ZONE 'Australia/Hobart')::date - INTERVAL '1 day')::date
            END AS day_9am_val
        FROM
            temp_export
    ) tbl

ORDER BY
    site_name, date_time_utc DESC

预期值作为 precip_since_9am 提供,计算值(应匹配)为 precip_since_9am_calday_9am_val 不是必需的,它只是说明我如何处理划分上午 9 点截止时间的问题。我已在 SQL fiddle here 中放置了一小部分数据,但还在下面显示了一些示例行:

站点名称 本地日期时间 沉淀_10分钟 precip_since_9am day_9am_val precip_since_9am_cal
网站 2024-01-18 17:00:00 0.2 10.8 2024-01-18 10.8
网站 2024-01-18 16:50:00 0.4 10.6 2024-01-18 10.6
网站 2024-01-18 16:40:00 0.2 10.2 2024-01-18 10.2
网站 2024-01-18 16:30:00 0.2 10 2024-01-18 10.0
网站 2024-01-18 16:20:00 0.4 9.8 2024-01-18 9.8
sql postgresql aggregate-functions weather
1个回答
0
投票

我最终根据 NickW 的建议重写以删除子选择,并将案例直接包含在分区字段中:

SELECT
    site_name,
    date_time_utc AT TIME ZONE 'Australia/Hobart'                                 AS date_time_local,
    precip_10min,
    precip_since_9am,
    SUM(precip_10min) OVER (PARTITION BY site_name, (CASE
                                                       WHEN (date_time_utc AT TIME ZONE 'Australia/Hobart')::time > '9:00'
                                                       THEN (date_time_utc AT TIME ZONE 'Australia/Hobart')::date
                                                       ELSE ((date_time_utc AT TIME ZONE 'Australia/Hobart')::date - INTERVAL '1 day')::date
                                                       END) ORDER BY date_time_utc) AS precip_since_9am_calc
FROM
    temp_export

ORDER BY
    site_name, date_time_utc DESC
© www.soinside.com 2019 - 2024. All rights reserved.