为什么在查看每个账户的当前余额时要使用 max(balance)? SQL 面试问题

Why should max(balance) be used when looking at current balance for each account? SQL interview question

有人问我这个问题 'Why do you need to use the max function on the balance column to get the current balance for each account?' 对于以下查询示例:

SELECT
    universe -- (bookmaker name)
    ,wallet_id
    ,sum(operator_balance_delta) as profit
    ,max(balance) as current_balance 
    
FROM 
    transactions
INNER JOIN
    (
        SELECT  
            id
            ,universe
            ,balance
        FROM 
            wallets -- (accounts table)
        WHERE 
            created_at BETWEEN '2021-01-01 00:00:00' AND '2021-02-01 00:00:00'
            AND currency = 'GBP'
            AND last_bet_at IS NOT NULL
            AND balance >= 0
            LIMIT 100
    ) AS accounts ON accounts.id = transactions.wallet_id

WHERE type_id IN (SELECT id FROM transaction_types WHERE code IN ('bet','casino-wager','virtualsports-wager','live-casino-wager','bingo-wager'))    
GROUP BY wallet_id,type_id,universe

据我所知,maximum 顾名思义就是给出帐户的最大余额,不一定是当前余额。我认为唯一可能的情况是,最大值是否以某种方式考虑了日期,因此返回最大值(日期)的余额,或者换句话说,当前余额。

如有任何帮助,我们将不胜感激!

您需要在此处使用聚合,因为 balance 列不是 GROUP BY 的一部分。 任何不在 GROUP BY 中的列必须有聚合。

max(balance) 不会 给你账户的最大余额,因为 balance 列来自 wallet table,而不是 transaction table。由于 wallet_idGROUP BY 的一部分,并且 balance 在功能上依赖于它,因此只有一个 balance 值。

这里真正应该发生的是 balance 应该在 GROUP BY 或者,transaction table应该在子查询中预先分组。

此查询的其他问题如下所示:

    应使用
  • Table 别名,列应引用 table 它们来自
  • created_at BETWEEN ... 可能是错误的,因为它包括终点。它应该使用半开区间 created_at >= ... AND created_at < ...
  • 子查询 type_id IN (SELECT ... 不是必需的,可以是一个普通的连接,因为 id 是一个主键
  • LIMIT 没有 ORDER BY 会给出不确定的结果

所以最终的查询应该是这样的,如果我写的话:

SELECT
    w.universe -- (bookmaker name)
    ,w.id as wallet_id
    ,sum(t.operator_balance_delta) as profit
    ,w.balance as current_balance 
    
FROM 
    transactions t
JOIN
    (
        SELECT  
            w.id
            ,w.universe
            ,w.balance
        FROM 
            wallets w -- (accounts table)
        WHERE 
            w.created_at >= '2021-01-01 00:00:00'
            AND w.created_at < '2021-02-01 00:00:00'
            AND w.currency = 'GBP'
            AND w.last_bet_at IS NOT NULL
            AND w.balance >= 0
        ORDER BY balance DESC
        LIMIT 100
    ) AS a ON a.id = t.wallet_id

JOIN transaction_types tt
  ON tt.type_id = t.id
  AND tt.code IN (
      'bet',
      'casino-wager',
      'virtualsports-wager',
      'live-casino-wager',
      'bingo-wager')
GROUP BY
  w.id,
  w.universe,
  w.balance,
  t.type_id;