我有下表(简化如下):
订单:
<id: 1, shipping: 6.0, price: 20.0>
<id: 2, shipping: 10.0, price: 30.0>
<id: 3, shipping: 7.0, price: 12.0>
<id: 4, shipping: 5.0, price: 0.0> #0 dollars because it was updated after return
销售
:
<id: 1, order_id: 1, price:10.0, qty:2, date: "2020-06-01T01:16:15-04:00">
<id: 2, order_id: 1, price:9.0, qty: 1, date: "2020-06-01T01:16:15-04:00">
<id: 3, order_id: 2, price:15.0, qty:2, date: "2020-06-01T01:23:53-04:00">
<id: 4, order_id: 3, price:4.0, qty: 1, date: "2020-06-01T20:28:18-04:00">
<id: 5, order_id: 3, price:4.0, qty: 2, date: "2020-06-01T20:31:15-04:00">
<id: 6, order_id: 4, price:29.0, qty:1, date: "2020-06-03T20:16:15-04:00">
退款
:
<id: 1, order_id: 1, qty:1, amount: 9.0, date: "2020-06-01T01:23:15-04:00">
<id: 2, order_id: 4, qty:1, amount: 29.0, date: "2020-06-04T03:34:53-04:00">
我正在编写原始sql来计算运费
(即sum(orders.shipping))、总订单
(即COUNT(DISTINCTorders.id))和净销售额
(即 sales.price * sales.qty - COALESCE(refunds.refund_amount, 0))按天分组。搜索将采用格式为 YYYY-MM-DDThh24:mi:ss
的 min_date
和 max_date
来过滤销售或退款不在日期范围内。我遇到的问题是使用 generate_series
添加表中不存在的所有日期,并将值全部设置为 0。因此,如果 min_date = 2020-06-01T00,则为示例响应:00:00 和 max_date = 2020-06-05T23:59:59 类似于:
"2020-06-01": {shipping: 6, total_orders: 3, net_sales: 62.0},
"2020-06-02": {shipping: 0, total_orders: 0, net_sales: 0}, --> newly added
"2020-06-03": {shipping: 5, total_orders: 1, net_sales: 29},
"2020-06-04": {shipping: 0, total_orders: 1, net_sales: -29.0},
"2020-06-05": {shipping: 0, total_orders: 0, net_sales: 0} --> newly added.
谁能帮我得到上面想要的结果。我看过一些例子,但我无法让它适合我的场景。谢谢!
最佳答案
我认为这会做你想要的:
select
d.dt,
o.shipping,
s.total_orders,
coalesce(s.sales_amount, 0) - coalesce(r.refound_amount, 0) net_sales
from generate_series(?::timestamp, ?::timestamp, interval '1 day') d(dt)
left join lateral (
select
count(distinct order_id) total_orders,
sum(price * quantity) sales_amount,
array_agg(order_id) order_ids
from sales s
where s.date >= d.dt and s.date < d.dt + interval '1 day'
) s on true
left join lateral (
select sum(o.shipping) shipping
from orders o
where o.id = any(s.order_ids)
) o on true
left join lateral (
select sum(r.amount) refound_amount
from refunds r
where r.order_id = any(s.order_ids)
) r on true
查询首先生成给定间隔内的所有日期(?
代表两个日期参数)。
然后,我们使用带有聚合查询的横向联接
来获取该期间内发生的所有销售的信息。另一个稍后加入
带来与第一个横向加入选择的order_id
相对应的运费,另一个带来相应的退款。
关于ruby-on-rails - Postgresql 使用原始 sql 填充缺失的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62489496/