为什么sql在结果中给出了不正确的总和?

时间:2015-02-19 19:37:49

标签: mysql sql left-join

Balance中的行:

enter image description here

Amount的类型为十进制10,1

我们选择:

SELECT
                u.UserID as UserID,

                (ifnull(b.BalanceDebit,0) - ifnull(bc.BalanceCredit, 0)) as Balance,
                ifnull(bc.BalanceCredit, 0) as BalanceCredit

            FROM 
                Users as u
            LEFT JOIN 
                    (
                        SELECT 
                            UserID,
                            SUM(Amount) as BalanceDebit
                        FROM
                            Balance
                        WHERE 
                            Operation='debit' AND StatusPay = 'success'
                        GROUP BY 
                            UserID
                    ) as b ON u.UserID = u.UserID
            LEFT JOIN 
                    (
                        SELECT 
                            UserID, 
                            SUM(Amount) as BalanceCredit
                        FROM
                            Balance
                        WHERE 
                            Operation='credit' AND StatusPay = 'success'
                        GROUP BY 
                            UserID
                    ) as bc ON bc.UserID = u.UserID

            WHERE 
                u.UserID != '12'

选择后,结果我们看到下一行:

enter image description here

但结果平衡不对。结果显示所有用户的余额均为10.0,但只有一个用户(UsersID = 40)具有10.0。

请告诉我哪里有错误的sql问题?如何正确选择总和?

4 个答案:

答案 0 :(得分:1)

您的问题是您的第一个LEFT OUTER JOIN:

ON u.UserID = u.UserID

应该是

ON u.UserID = b.UserID

另外,如果你想找到余额,我想你会拿走所有的积分,并减去所有的借记。所以不要这样:

ifnull(b.BalanceDebit,0) - ifnull(bc.BalanceCredit, 0)

不应该是这个吗?

ifnull(b.BalanceCredit,0) - ifnull(bc.BalanceDebit, 0)

答案 1 :(得分:1)

不需要子查询,可以像这样实现相同的结果:

SELECT
    u.UserID,
    SUM(CASE WHEN b.operation = 'debit' THEN b.operation ELSE 0 END) balance_debit,
    SUM(CASE WHEN b.operation = 'credit' THEN b.operation ELSE 0 END) balance_credit,
    SUM(CASE WHEN b.operation = 'debit' THEN b.operation ELSE 0 END) -
        SUM(CASE WHEN b.operation = 'credit' THEN b.operation ELSE 0 END) balance
FROM users u
LEFT JOIN
    balance b
    ON u.UserID = b.UserID AND b.StatusPay = 'success'
WHERE u.UserID <> 12
GROUP BY u.USERID

答案 2 :(得分:0)

两个左连接都可以使用CASE组合成一个(并修复坏连接条件):

SELECT
    u.UserID AS UserID,

    (ifnull(b.BalanceDebit,0) - ifnull(b.BalanceCredit, 0)) AS Balance,
    ifnull(b.BalanceCredit, 0) AS BalanceCredit

FROM 
    Users AS u
LEFT JOIN 
        (
            SELECT 
                UserID,
                SUM(CASE WHEN Operation='debit' AND StatusPay = 'success' THEN Amount end) AS BalanceDebit,
                SUM(CASE WHEN Operation='credit' AND StatusPay = 'success' THEN Amount end) AS BalanceCredit
            FROM
                Balance
            WHERE 
                (Operation='debit' AND StatusPay = 'success')
              OR
                (Operation='credit' AND StatusPay = 'success')
            GROUP BY 
                UserID
        ) AS b ON b.UserID = u.UserID

答案 3 :(得分:0)

Bill Gregg指出的JOIN条件是导致结果失败的主要原因。可以重写查询以避免必须两次加入平衡:

SELECT u.UserID
, COALESCE(b.CalculatedBalance, 0)
, COALESCE(b.BalanceCredit, 0)
FROM Users AS u
LEFT JOIN
  (SELECT UserID,
    SUM(CASE Operation
      WHEN 'debit' THEN Amount*-1
      WHEN 'credit' THEN Amount
    END) AS CalculatedBalance,
    SUM(CASE Operation
      WHEN 'credit' THEN Amount
    END) AS BalanceCredit
  FROM Balance
  WHERE StatusPay  = 'success'
  GROUP BY UserID
  ) AS b
ON u.UserID = b.UserID
WHERE u.UserID != '12'