SQL嵌套请求

问题描述 投票:1回答:1

我有3张桌子:

  1. transaction - 关于用户余额变化的一般信息。 primary key : transaction_id
  2. bet_transactions - 有关投注的特殊信息,foreign key : transaction_id
  3. win_transaction - 与bet_transactions相同,但包含wins

我想得到所有赌注和胜利的总和。我想出了这个:

select
    u.username as username,
    u.balance as balance,
    sum(bt.amount) as bet_sum,
    sum(wt.amount) as win_sum
from
    users u,
    (
        select 
            t.*
        from 
            transactions t,
            bet_transactions b
        where 
            t.transaction_id = b.transaction_id
    ) bt,
    (
        select 
            t.*
        from 
            transactions t,
            win_transactions w
        where 
            t.transaction_id = w.transaction_id
    ) wt
where
    u.username = bt.username and
    u.username = wt.username
group by
    u.username

它不能正常工作:我总是只得到一行而且总和不正确。但是,如果我删除这样的嵌套部分之一,它会按预期开始工作。我究竟做错了什么?

select
    u.username as username,
    u.balance as balance,
    sum(bt.amount) as bet_sum
from
    users u,
    (
        select 
            t.*
        from 
            transactions t,
            bet_transactions b
        where 
            t.transaction_id = b.transaction_id
    ) bt
where
    u.username = bt.username
group by
    u.username
sql postgresql
1个回答
2
投票

将聚合函数和分组移动到嵌套的子查询,如下所示:

select
    u.username as username,
    u.balance as balance,
    bt.bet_sum,
    wt.win_sum
from
    users u
    left outer join 
    (
        select 
            t.username, sum(b.amount) as bet_sum
        from 
            transactions t,
            bet_transactions b
        where 
            t.transaction_id = b.transaction_id
        group by
            t.username
    ) bt
       on u.username = bt.username
    left outer join
    (
        select 
            t.username, sum(w.amount) as win_sum
        from 
            transactions t,
            win_transactions w
        where 
            t.transaction_id = w.transaction_id
        group by
            t.username
    ) wt
        on u.username = wt.username

CTE更具可读性:

WITH 
bt as 
     (
        select 
            t.username, sum(b.amount) as bet_sum
        from 
            transactions t,
            bet_transactions b
        where 
            t.transaction_id = b.transaction_id
        group by
            t.username
    ),
wt as
    (
        select 
            t.username, sum(w.amount) as win_sum
        from 
            transactions t,
            win_transactions w
        where 
            t.transaction_id = w.transaction_id
        group by
            t.username
    ) 
select
    u.username as username,
    u.balance as balance,
    bt.bet_sum,
    wt.win_sum
from
    users u
    left outer join bt
       on u.username = bt.username
    left outer join wt
        on u.username = wt.username

编辑:

我切换到正确的ANSI连接语法,也切换到外连接和CTE。感谢@ThorstenKettner关于建议。

© www.soinside.com 2019 - 2024. All rights reserved.