【问题标题】:postgresql column sums across a join, grouped by another column跨连接的postgresql列总和,按另一列分组
【发布时间】:2021-05-07 13:07:17
【问题描述】:

假设我有以下 PostgreSQL 表:

表:foo

foo_id, baz, amount
--------------------
f1, b1, 500
f2, b1, 500
f3, b2, 1000
f4, b3, 100

表:bar

bar_id, foo_id, amount
--------------------
br1, f1, 10
br2, f1, 10
br3, f1, 10
br4, f2, 10
br5, f2, 10
br6, f3, 750
br7, f3, 250
br8, f4, 90
br9, f4, 9

我的目标是总结foo.amountbar.amount,找出区别,按foo.baz分组。

示例结果:

baz, sum_foo_amount, sum_bar_amount, diff_foo_bar
-------------------------------------------------
b1, 1000, 50, 950
b2, 1000, 1000, 0
b3, 100, 99, 1

我设法使用几个 CTE 获得了预期的结果——一个总结 foo,一个总结 bar——然后从 foo 中选择并分组。但我实际上正在为 bar 处理大约 1m 行,至少可以说它不是性能。

我有信心最终可以拼凑出一些东西,但我很想知道我可能看不到的模式或方法的见解。

【问题讨论】:

    标签: postgresql join sum


    【解决方案1】:

    你可以试试这样的

    select 
        a.baz, a.amount,b.amount,a.amount-b.amount
    from 
        (select baz,sum(amount) as amount from foo group by baz) as a,
        (select foo_id,sum(amount) as amount from foo group by foo_id) as b
    where
        a.baz = b.foo_id
    

    【讨论】:

    • 我很抱歉@Philippe,bar.foo_id 的表格数据不正确;它确实指向foo.baz,而是foo.foo_id。因此,最后一个 where 将无法从您的 - 善意提供的 - 解决方案中工作。我已经更新了。
    • 很抱歉,我不明白这两个表之间的关系。foo 表中 b1 的总和是可以的。但是当 f1 只有 30 时,你怎么能在 bar 中有“50”?这里有些不对劲。你能解释一下吗?
    • 50 来自bar.foo_id --> foo.foo_idf1f2),然后是bar.amount 的总和,由foo.bazb1)分组。
    • foo 和 bar 是什么关系。在该表的描述中,您无法知道 foo.b1 = sum(bar.f1) + sum(bar.f2)。没有唯一的键来建立你想要的关系。
    • 感谢您坚持这一点。我找到了解决方案,但仍然对更好的方法感到好奇。查看bar 的前5 行。他们都 FK 到 foo.f1foo.f2。需要的一条信息是foo.f1 --> amount + foo.f2 --> amount 的总和。 foo.f1foo.f2 的重要之处在于它们共享 foo.baz = b1。将它们视为“存款”,foo.baz=b1 表示它们进入了同一个帐户。然后将bar 行视为“提款”;它们与存款有关 (foo.foo_id),但它们“来自”同一个帐户 b1
    【解决方案2】:

    不是我最自豪的问题之一回答,而是发布当前正在使用的解决方案以供后代使用:

    select    
        baz,
        foo_sum,
        bar_sum,
        (foo_sum - bar_sum) as difference
    from    
        (
        with x as (
            select           
                foo.baz as baz,
                cast(foo.amount as decimal) as foo_sum,
                cast(sum(bar.amount) as decimal) as bar_sum
            from bar
            inner join foo on bar.foo_id = foo.foo_id        
            group by bar.foo_id, foo.baz, foo.amount
        )
    select       
           x.baz as baz,
           sum(x.foo_sum) as foo_sum,
           sum(x.bar_sum) as bar_sum
    from x
    group by x.baz
        ) as foo_bar_calculations;
    

    产生结果:

     baz | foo_sum | bar_sum | difference 
    -----+---------+---------+------------
     b2  |    1000 |    1000 |          0
     b3  |     100 |      99 |          1
     b1  |    1000 |      50 |        950
    (3 rows)
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-25
      • 1970-01-01
      • 2011-11-01
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 2018-08-12
      • 1970-01-01
      相关资源
      最近更新 更多