Fill in missing rows when aggregating over multiple fields in Postgres

后端 未结 2 1392
温柔的废话
温柔的废话 2021-01-18 08:35

I am aggregating sales for a set of products per day using Postgres and need to know not just when sales do happen, but also when they do not for further processing.

相关标签:
2条回答
  • 2021-01-18 09:05
    select 
        date, 
        count(sale_id) as sales, 
        product
    from
        sales_data
        right join (
            (
                select d::date as date
                from generate_series (
                    (select min(date) from sales_data),
                    (select max(date) from sales_data),
                    '1 day'
                ) gs (d)
            ) gs
            cross join
            (select distinct product from sales_data) p
        ) cj using (product, date)
    group by product, date
    order by product, date
    
    0 讨论(0)
  • 2021-01-18 09:23

    You could use:

    WITH cte AS (
       SELECT date, s.product
       FROM  ... -- some way to generate date series
       CROSS JOIN (SELECT DISTINCT product FROM sales_data) s
    )
    SELECT 
        c.date,
        c.product,
        COUNT(sd.sale_id) AS sales
    FROM cte c
    LEFT JOIN sales_data sd
      ON c.date = sd.date AND c.product= sd.product
    GROUP BY c.date, c.product
    ORDER BY c.date, c.product;
    

    First create Cartesian product of dates and products, then LEFT JOIN to actual data and do calculations.


    Oracle has great feature for this scenarios called Partitioned Outer Joins:

    SELECT times.time_id, product, quantity 
    FROM inventory  PARTITION BY  (product) 
    RIGHT OUTER JOIN times ON (times.time_id = inventory.time_id) 
    WHERE times.time_id BETWEEN TO_DATE('01/04/01', 'DD/MM/YY') 
          AND TO_DATE('06/04/01', 'DD/MM/YY') 
    ORDER BY  2,1; 
    
    0 讨论(0)
提交回复
热议问题