I have a query which get data summarised between two dates like so:
SELECT date(created_at), COUNT(COALESCE(id, 0)) AS total_orders, SUM(COALESCE(total_price, 0)) AS total_price, SUM(COALESCE(taxes, 0)) AS taxes, SUM(COALESCE(shipping, 0)) AS shipping, AVG(COALESCE(total_price, 0)) AS average_order_value, SUM(COALESCE(total_discount, 0)) AS total_discount, SUM(total_price - COALESCE(taxes, 0) - COALESCE(shipping, 0) - COALESCE(total_discount, 0)) as net_sales FROM orders WHERE shop_id = 43 AND orders.active = true AND orders.created_at >= '2022-07-20' AND orders.created_at <= '2022-07-26' GROUP BY date (created_at) order by created_at::date desc
However for dates that do not have any orders, the query returns nothing and I’d like to return 0
.
I have tried with COALESCE
but that doesn’t seem to do the trick?
Any suggestions?
Advertisement
Answer
Please refer to the below script.
SELECT * FROM (SELECT date(created_at) AS created_at, COUNT(id) AS total_orders, SUM(total_price) AS total_price, SUM(taxes) AS taxes, SUM(shipping) AS shipping, AVG(total_price) AS average_order_value, SUM(total_discount) AS total_discount, SUM(total_price - taxes - shipping - total_discount) AS net_sales FROM orders WHERE shop_id = 43 AND orders.active = true AND orders.created_at >= '2022-07-20' AND orders.created_at <= '2022-07-26' GROUP BY date (created_at) UNION SELECT dates AS created_at, 0 AS total_orders, 0 AS total_price, 0 AS taxes, 0 AS shipping, 0 AS average_order_value, 0 AS total_discount, 0 AS net_sales FROM generate_series('2022-07-20', '2022-07-26', interval '1 day') AS dates WHERE dates NOT IN (SELECT created_at FROM orders WHERE shop_id = 43 AND orders.active = true AND orders.created_at >= '2022-07-20' AND orders.created_at <= '2022-07-26' ) ) a ORDER BY created_at::date desc;
There is one sample for your reference. Sample
I got your duplicate test cases at my side. The root cause is created_at field (datattype:timestamp), hence there are duplicate lines.
Below script is correct for your request.
SELECT * FROM (SELECT date(created_at) AS created_at, COUNT(id) AS total_orders, SUM(total_price) AS total_price, SUM(taxes) AS taxes, SUM(shipping) AS shipping, AVG(total_price) AS average_order_value, SUM(total_discount) AS total_discount, SUM(total_price - taxes - shipping - total_discount) AS net_sales FROM orders WHERE shop_id = 43 AND orders.active = true AND orders.created_at >= '2022-07-20' AND orders.created_at <= '2022-07-26' GROUP BY date (created_at) UNION SELECT dates AS created_at, 0 AS total_orders, 0 AS total_price, 0 AS taxes, 0 AS shipping, 0 AS average_order_value, 0 AS total_discount, 0 AS net_sales FROM generate_series('2022-07-20', '2022-07-26', interval '1 day') AS dates WHERE dates NOT IN (SELECT date (created_at) FROM orders WHERE shop_id = 43 AND orders.active = true AND orders.created_at >= '2022-07-20' AND orders.created_at <= '2022-07-26' ) ) a ORDER BY created_at::date desc;
Here is a sample that’s same with your side. Link