【问题标题】:PostgreSQL LEFT JOIN with SUM & Arithmetic OperatorsPostgreSQL LEFT JOIN 与 SUM 和算术运算符
【发布时间】:2021-03-17 05:39:14
【问题描述】:

我正在尝试使用 3 个表的 SUM 和算术运算符进行 LEFT JOIN,但我被卡住了,

在下面底部的预期结果中,有一个名为initial_stock 的新字段,它是以下结果:

initial_stock = current_stock + sum(used) - sum(restock_amount)

你可以在这里试试:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=2216e64ee6fa90556d8f952f115dd070

这是表格:

product表:

id      product_name  current_stock    
------  ------------  -------------  
  1     abc           10  
  2     aaa           0  
  3     bbb           10  
  4     ddd           20    

usage表:

id      product_id    used     date_out
------  ------------  -------  ----------
  1     1             10       2020-11-20
  2     1             20       2020-11-20
  3     2             20       2020-11-11

product_restock表:

id      product_id    restock_amount  date_in
------  ------------  --------------  -----------
  1     1             10              2020-11-15
  2     1             20              2020-11-14
  3     4             10              2020-11-09

预期结果从日期2020-11-012020-11-30

id      product_name  initial_stock restock used current_stock
------  ------------  ------------- ------- ---- -------------
  1     abc             10          30      30   10
  2     aaa             20          0       20   0
  3     bbb             10          0       0    10    
  4     ddd             10          10      0    20

【问题讨论】:

    标签: sql postgresql sum left-join lateral-join


    【解决方案1】:

    您可以为此使用横向连接:

    select p.*, u.used, pr.restock_amount, 
        p.current_stock + u.used - pr.restock_amount as initial_stock
    from product p
    cross join lateral (
        select coalesce(sum(u.used), 0) as used
        from usage u 
        where u.product_id = p.id and u.date_out between '2020-11-01'::date and '2020-11-30'::date
    ) u
    cross join lateral (
        select coalesce(sum(u.restock_amount), 0) as restock_amount
        from product_restock pr 
        where pr.product_id = p.id and pr.date_out between '2020-11-01'::date and '2020-11-30'::date
    ) pr
    

    【讨论】:

    • 结果错误,dbfiddle.uk/…
    • @Diand:p.product_id 必须是 p.id。固定。
    【解决方案2】:

    分别聚合在usageproduct_restock,然后加入product

    select p.id, p.product_name,
           p.current_stock  + coalesce(u.used, 0) - coalesce(r.restock, 0) initial_stock,
           coalesce(r.restock, 0) restock,
           coalesce(u.used, 0) used,
           p.current_stock
    from product p
    left join (select product_id, sum(used) used from usage where date_out between '2020-11-01' and '2020-11-30' group by product_id) u
    on u.product_id = p.id
    left join (select product_id, sum(restock_amount) restock from product_restock where date_in between '2020-11-01' and '2020-11-30' group by product_id) r
    on r.product_id = p.id
    

    请参阅demo
    结果:

    > id | product_name | initial_stock | restock | used | current_stock
    > -: | :----------- | ------------: | ------: | ---: | ------------:
    >  1 | abc          |            10 |      30 |   30 |            10
    >  2 | aaa          |            20 |       0 |   20 |             0
    >  3 | bbb          |            10 |       0 |    0 |            10
    >  4 | ddd          |            10 |      10 |    0 |            20
    

    【讨论】:

    • 按预期工作!谢谢!!
    • 我忘记了,您需要在答案中添加where 日期过滤器,以便我可以将您的答案标记为已接受。像这样的东西:dbfiddle.uk/… 也许? @forpas
    • @Diand 是的,您可以在子查询中设置您需要的任何条件,但是如果 initial_stock 是指您搜索期间之前的股票,这是否会返回正确的 initial_stock?我认为在这种情况下正确的公式是:initial_stock = (current_stock at the end of that period) + (sum(used) of that period) - (sum(restock_amount) of that period).
    • 嗯,我也不确定,你能为那个可能的正确答案创建第二个选项吗?当前的答案没有抛出任何错误,但我认为我需要使用您认为是正确公式且具有更多数据的选项对其进行测试。
    • 没有更多数据无法测试,当然您必须知道您的预期结果。
    猜你喜欢
    • 1970-01-01
    • 2014-05-23
    • 2015-08-21
    • 1970-01-01
    • 2021-01-30
    • 2012-03-21
    • 1970-01-01
    • 2022-01-07
    • 2019-01-05
    相关资源
    最近更新 更多