【问题标题】:Last three months average for each month in PostgreSQL queryPostgreSQL查询中每个月的最近三个月平均值
【发布时间】:2011-11-11 03:12:31
【问题描述】:

我正在尝试在 Postgresql 中构建一个用于预算的查询。

我目前有一个按月分组的数据列表。

对于一年中的每个月,我需要检索前三个月的平均月销售额。例如,在 1 月份,我需要上一年 10 月到 12 月的平均月销售额。所以结果会是这样的:

1  12345.67
2  54321.56
3  242412.45

这是按月份分组的。

这是我的查询中的一段代码,它将获得当月的销售额:

LEFT JOIN (SELECT SUM((sti.cost + sti.freight) * sti.case_qty * sti.release_qty)
                  AS trsf_cost,
                  DATE_PART('month', st.invoice_dt) as month
             FROM stransitem sti, 
                  stocktrans st
            WHERE sti.invoice_no = st.invoice_no 
              AND st.invoice_dt >= date_trunc('year', current_date) 
              AND st.location_cd = 'SLC' 
              AND st.order_st != 'DEL'
         GROUP BY month) as trsf_cogs ON trsf_cogs.month = totals.month

我需要另一个可以得到相同结果的加入,只是前 3 个月的平均值,但我不确定如何。

这始终是 1 月至 12 月 (1-12) 的列表,从 1 月开始,到 12 月结束。

【问题讨论】:

    标签: sql postgresql aggregate-functions


    【解决方案1】:

    这是一个窗口函数的经典问题。解决方法如下:

    SELECT month_nr
          ,(COALESCE(m1, 0)
          + COALESCE(m2, 0)
          + COALESCE(m3, 0))
          /
          NULLIF ( CASE WHEN m1 IS NULL THEN 0 ELSE 1 END
                 + CASE WHEN m2 IS NULL THEN 0 ELSE 1 END
                 + CASE WHEN m3 IS NULL THEN 0 ELSE 1 END, 0) AS avg_prev_3_months
          -- or divide by 3 if 3 previous months are guaranteed or you don't care
    FROM   (
        SELECT date_part('month', month) as month_nr
              ,lag(trsf_cost, 1) OVER w AS m1
              ,lag(trsf_cost, 2) OVER w AS m2
              ,lag(trsf_cost, 3) OVER w AS m3
        FROM  (
            SELECT date_part( 'month', month) as trsf_cost -- some dummy nr. for demo
                              ,month
            FROM   generate_series('2010-01-01 0:0'::timestamp
                                  ,'2012-01-01 0:0'::timestamp, '1 month') month
            ) x
        WINDOW w AS (ORDER BY month)
        ) y;
    

    这要求永远不会缺一个月!否则,请查看此相关答案:
    How to compare the current row with next and previous row in PostgreSQL?

    每月计算正确的平均值。如果只有前两个飞蛾然后除以 2,等等。如果没有前一个。月,结果为 NULL。

    在您的子查询中,使用

    date_trunc('month', st.invoice_dt)::date AS month
    

    而不是

    DATE_PART('month', st.invoice_dt) as month
    

    这样您就可以轻松地对多年来的月份进行排序!

    更多信息

    【讨论】:

    • 工作就像一个魅力。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    相关资源
    最近更新 更多