【问题标题】:Calculate balance with mysql用mysql计算余额
【发布时间】:2012-03-12 18:12:20
【问题描述】:

我有一个包含以下数据的表:

ID      In       Out 
1      100.00    0.00   
2       10.00    0.00   
3        0.00   70.00    
4        5.00    0.00    
5        0.00   60.00   
6       20.00    0.00     

现在我需要一个查询,它会给出以下结果:

ID      In       Out    Balance
1      100.00    0.00   100.00
2       10.00    0.00   110.00
3        0.00   70.00    40.00
4        5.00    0.00    45.00
5        0.00   60.00   -15.00
6       20.00    0.00     5.00

是否可以通过一个查询来执行此操作,而不使用触发器或存储过程?

【问题讨论】:

    标签: mysql sql cumulative-sum balance


    【解决方案1】:

    简短的回答,是的

    更长的答案,您可以使用一个变量来计算它,因为它向下迭代行,即

    SELECT 
        `table`.`ID`,
        `table`.`In`,
        `table`.`Out`,
        @Balance := @Balance + `table`.`In` - `table`.`Out` AS `Balance`
    FROM `table`, (SELECT @Balance := 0) AS variableInit
    ORDER BY `table`.`ID` ASC
    

    , (SELECT @Balance := 0) AS variableInit 确保在您开始之前将 @Balance 初始化为 0。对于每一行,它将@Balance 设置为@Balance + In - Out,然后输出计算值。

    还值得确定 ORDER 是一致的,否则余额将根据返回的行的顺序而有所不同。例如,如果您想将其重新排序,则可以将其用作子查询,因为外部查询处理计算的值,从而确保余额保持正确,即

    SELECT
        `balanceCalculation`.`ID`,
        `balanceCalculation`.`In`,
        `balanceCalculation`.`Out`,
        `balanceCalculation`.`Balance`
    FROM (
        SELECT 
            `table`.`ID`,
            `table`.`In`,
            `table`.`Out`,
            @Balance := @Balance + `table`.`In` - `table`.`Out` AS `Balance`
        FROM `table`, (SELECT @Balance := 0) AS variableInit
        ORDER BY `table`.`ID` ASC
    ) AS `balanceCalculation`
    ORDER BY `balanceCalculation`.`ID` DESC
    

    【讨论】:

    • 如何分页,我认为这个查询不会很好,平衡也不会很好
    • @PutraLZendrato 恐怕我不明白这个问题
    • 你好西蒙,我的意思是,如果数据行很大,例如,我们有 100 条数据,但不会在一页中加载。因此,我们分成 2 页(分页工作)。我认为运行平衡将不起作用。
    • 您可以限制外部查询,因为子查询从完整数据集中计算派生值。您可以将balanceCalculation 想象成另一张桌子。该限制不会更改总数,只会更改您从中选择的数据子集。
    • 有没有办法让它与分页一起工作?
    【解决方案2】:

    最简单的答案是:

    SELECT `ID`, 
           `In`, 
           `Out`, 
           @running_bal := @running_bal + (`In` - `Out`)  as `Balance`
    FROM   tableName, (SELECT @running_bal := 0) tempName
    

    【讨论】:

      【解决方案3】:

      一个简单的LEFT JOIN 就足够了:

      SELECT t.ID, t.In, t.Out, (SUM(t2.In) - SUM(t2.Out)) Balance
      FROM mytable t
          LEFT JOIN mytable t2 ON b2.ID <= b.ID
      GROUP BY b.ID
      

      或子查询(事实证明它的速度大约是原来的两倍)

      SELECT t.ID, t.In, t.Out,
          (SELECT SUM(t2.In) - SUM(t2.Out) FROM mytable t2 WHERE t2.ID <= t.ID) Balance
      FROM mytable t;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-01
        • 2015-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多