Postgresql - 在聚合查询中聚合查询

Postgresql - Aggregate queries inside aggregate queries

我正在为使用 postgresql tables 的销售代表佣金报告构建一个 select 语句。我希望它显示这些列: -客户编号

-零件号

-月初至今的数量(MTD 数量)

-年初至今数量(YTD 数量)

-月初至今的扩展售价(MTD 扩展)

-年初至今的扩展售价(YTD 扩展)

数据在两个table中:

Sales_History(每张发票一条记录,此 table 包括客户编号和发票日期)

Sales_History_Items(每张发票每个零件号一条记录,这 table 包括零件号、数量和单价)。

如果我做一个结合这两个 table 的简单查询,这就是它的样子:

日期/客户/零件/数量/单价

4 月 1 日/ABC Co./WIDGET/5/11 美元

4 月 4 日/ABC Co./WIDGET/8/11.50 美元

4 月 1 日 / ABC 公司 / 小工具 / 1 / 30 美元

4 月 7 日/XYZ Co./WIDGET/3/11.50 美元

这是我想要的最终结果(每个客户每个零件一行):

客户/零件/数量/MTD 数量/MTD 销售额/YTD 数量/YTD 销售额

ABC 公司/WIDGET/13/147 美元/1500 美元/16,975 美元

ABC 公司 / 小工具 / 1 / $30 / 7 / $210

XYZ 公司/WIDGET/3/34.50 美元/18/203.40 美元

到目前为止,我已经能够想出这个 SQL 语句,这并没有让我得到每行的扩展销售列 (committed_qty * unit_price) 然后按客户编号/零件编号汇总它们,这就是我的问题:

with mtd as
(SELECT sales_history.cust_no, part_no, Sum(sales_history_items.committed_qty) AS MTDQty
    FROM sales_history left JOIN sales_history_items 
    ON sales_history.invoice_no = sales_history_items.invoice_no where  sales_history_items.part_no is not null and sales_history.invoice_date >= '2020-04-01' and sales_history.invoice_date <= '2020-04-30' 
    GROUP BY sales_history.cust_no, sales_history_items.part_no),

ytd as 
(SELECT sales_history.cust_no, part_no, Sum(sales_history_items.committed_qty) AS YTDQty
    FROM sales_history left JOIN sales_history_items 
    ON sales_history.invoice_no = sales_history_items.invoice_no where sales_history_items.part_no is not null and sales_history.invoice_date >= '2020-01-01' and sales_history.invoice_date <= '2020-12-31' GROUP BY sales_history.cust_no, sales_history_items.part_no),

mysummary as
(select MTDQty, YTDQty, coalesce(ytd.cust_no,mtd.cust_no) as cust_no,coalesce(ytd.part_no,mtd.part_no) as part_no
from ytd full outer join mtd on ytd.cust_no=mtd.cust_no and ytd.part_no=mtd.part_no)

select * from mysummary;

我认为我必须在此处嵌套另外几个聚合查询,这些查询将按 cust_no、part_no、unit_price 分组,但随后有那些扩展价格总计 (qty * unit_price) 由cust_no, part_no.

总结

如有任何帮助,我们将不胜感激。谢谢!

如果我没看错的话,你可以做条件聚合:

select sh.cust_no, shi.part_no,
    sum(shi.qty)  mtd_qty, 
    sum(shi.qty * shi.unit_price) ytd_sales,
    sum(shi.qty) filter(where sh.invoice_date >= date_trunc('month', current_date) mtd_qty, 
    sum(shi.qty * shi.unit_price) filter(where sh.invoice_date >= date_trunc('month', current_date) mtd_sales 
from sales_history sh
left join sales_history_items shi on sh.invoice_no = shi.invoice_no 
where  shi.part_no is not null and sh.invoice_date >= date_trunc('year', current_date)
group by sh.cust_no, shi.part_no

逻辑是过滤当前年份,并使用简单的聚合来计算“年初至今”的数字。要获得“月初至今”列,我们只需过滤聚合函数即可。

使用 filter 表达式一次性完成:

with params as (
  select '2020-01-01'::date as year, 4 as month
)
SELECT h.cust_no, i.part_no, 
       SUM(i.committed_qty) AS YTDQty,
       SUM(i.committed_qty * i.unit_price) as YTDSales,
       SUM(i.committed_qty) FILTER 
         (WHERE extract('month' from h.invoice_date) = p.month) as MTDQty,
       SUM(i.committed_qty * i.unit_price) FILTER
         (WHERE extract('month' from h.invoice_date) = p.month) as MTDSales
  FROM params p
       CROSS JOIN sales_history h
       LEFT JOIN sales_history_items i
              ON i.invoice_no = h.invoice_no 
 WHERE i.part_no is not null 
   AND h.invoice_date >= p.year 
   AND h.invoice_date < p.year + interval '1 year' 
 GROUP BY h.cust_no, i.part_no