【问题标题】:PostgreSQL subquery - calculating average of lagged valuesPostgreSQL 子查询 - 计算滞后值的平均值
【发布时间】:2020-07-05 19:57:08
【问题描述】:

我正在按月查看销售率,并且能够查询第一个表。我对 PostgreSQL 很陌生,正在尝试弄清楚如何查询第二个(我现在必须在 Excel 中做第二个) 我有当前的销售率,我想将其与 1 个月和 2 个月前的销售率进行比较,作为平均率。

我并不是要回答如何准确地解决它,因为这不是变得更好的重点,而只是为了提示使用特定于 PostgreSQL 的函数。我要计算的是基于第二张表的滞后值的第二张表中的 2 个月平均值。谢谢!

这是第一个表的查询:

with t1 as
    (select date,
            count(sales)::numeric/count(poss_sales) as SR_1M_before 
            from data
    where date between '2019-07-01' and '2019-11-30'
            group by 1),
     t2 as
    (select date,
            count(sales)::numeric/count(poss_sales) as SR_2M_before 
            from data
    where date between '2019-07-01' and '2019-10-31'
            group by 1)
select t0.date,
       count(t0.sales)::numeric/count(t0.poss_sales) as Sales_Rate 
       t1.SR_1M_before,
       t2.SR_2M_before
        from data as t0
        left join t1 on t0.date=t1.date
        left join t2 on t0.date=t1.date
        where date between '2019-07-01' and '2019-12-31'
group by 1,3,4
order by 1;

【问题讨论】:

  • 请告诉我们您当前的查询。
  • “两个月平均值”可以用窗函数计算:avg(sales_rate) over (order by "date" range between '2 month' preceding and current row)如果你每个月总是有一行,你也可以使用rows between 2 preceding and current row)
  • @GMB:添加了我当前的查询

标签: sql postgresql function subquery lag


【解决方案1】:

正如 a_horse_with_no_name 所评论的,您可以使用窗口函数通过 range 子句获取前两个月的平均值:

select 
    date,
    count(sales)::numeric/count(poss_sales) as Sales_Rate,
    avg(count(sales)::numeric/count(poss_sales)) over(
        order by date
        rows between '2 month' preceding and '1 month' preceding
    ) Sales_Rate,
    count(sales)::numeric/count(poss_sales) as Sales_Rate 
        - avg(count(sales)::numeric/count(poss_sales)) over(
            order by date
            rows between '2 month' preceding and '1 month' preceding
        ) PercentDeviation
from data
where date between '2019-07-01' and '2019-12-31'
group by date
order by date;

【讨论】:

    【解决方案2】:

    您的数据有点混乱 - 如果您有小数位(即 58% 是 57% 的平均值,而 58% 并不明显),则不会那么混乱。

    因为您希望在前两行有 NULL 值,所以我将使用 sum()count() 来计算值:

    with q as (
          <whatever generates the data you have shown>
         )
    select q.*,
           (sum(sales_rate) over (order by date
                                  rows between 2 preceding and 1 preceding
                                 ) /
            nullif(count(*) over (order by date
                                  rows between 2 preceding and 1 preceding
                                 )
           ) as two_month_average
    from q;
    

    您也可以使用caseavg() 来表达这一点:

    select q.*,
           (case when row_number() over (order by date) > 2)
                 then avg(sales_rate) over (order by date
                                            rows between 2 preceding and 1 preceding
                                           )
            end) as two_month_average
    from q;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多