如何在mysql选择查询中引用上一行

时间:2014-09-24 13:21:37

标签: mysql sql mamp

首先,我是一名sql菜鸟,只知道基础知识。我试过谷歌搜索(并看到一些类似的参考和例子,但我无法遵循或适用于我的问题),如果在我的情况下,我甚至不是100%。我正在尝试弄清楚如何执行一个选择,该选择涉及根据前一行中的列计算列。我希望从以前的平衡是下一个的进位:

我有一个交易清单

 _____________________________________________
| id |   Date    |  time |  amount |  type    |
|  1 |2014-01-01 | 12:00 |   2000  |  payin   |
|  5 |2014-01-01 | 17:00 |    -20  |  payout  |
|  2 |2014-01-01 | 18:00 |    -20  |  payout  |
|  3 |2014-01-02 | 12:00 |    -10  |  payout  |
|  4 |2014-01-03 | 12:00 |   +300  |  payin   |

正如您所看到的那样,有一个id(这是主键),但其订单无法保证,因为交易可能会过时并在最近的交易完成后添加。我想得到以下但我完全迷失了。 SQL根本不是我的区域。

|   Date    |  time |  carry  |   amount | balance  |  type   |
|2014-01-01 | 12:00 |       0 |    2000  |     2000 |  payin  |
|2014-01-01 | 17:00 |    2000 |     -20  |     1980 |  payout |
|2014-01-01 | 17:00 |    1980 |     -20  |     1960 |  payout |
|2014-01-02 | 12:00 |    1960 |     -10  |     1950 |  payout |
|2014-01-03 | 12:00 |    1950 |      -1  |     1949 |  payout |
|2014-01-03 | 12:00 |    1949 |      -5  |     1944 |  payout |
|2014-01-03 | 12:00 |    1944 |    +300  |     2244 |  payin  |

反过来我相信我可以通过基于类型和按日期分组的总结来获得以下内容

|   Date    |  carry  | total in | total out | balance | 
|2014-01-01 |       0 |    2000  |      -40  |   1960  | 
|2014-01-02 |    1960 |       0  |      -10  |    1950 | 
|2014-01-03 |    1950 |     300  |       -6  |    2244 | 

到目前为止,我通过使用以下查询(所有单独执行)查询Nodejs中每个日期特定日期的mysql数据库来获得所需结果:

var sql_init_Balance_day ='select sum(amount) as total '+
                        'from transactions '+
                        'Where transaction_date<\''+mdate.format('YYYY-MM-DD')+'\'';

var sql_closing_Balance_day ='select sum(amount) as closingBalance '+
                        'from transactions '+
                        'Where transaction_date<\''+mtomorrow.format('YYYY-MM-DD')+'\'';

var sql_payins_day = 'select sum(amount) as deposits '+
                        'from transactions '+
                        'Where transaction_date=\''+mdate.format('YYYY-MM-DD')+'\''+
                        ' and type=\'payin\'';

var sql_payouts_day = 'select sum(amount) as deductions '+
                        'from transactions '+
                        'Where transaction_date=\''+mdate.format('YYYY-MM-DD')+'\' '+
                        'and type=\'payout\'';

4 个答案:

答案 0 :(得分:1)

您可以使用变量计算进位

select `Date`, max(case when rowNum = 1 then carry end) carry,
    sum(case when type = 'payin' then amount else 0 end) total_in,
    sum(case when type = 'payout' then amount else 0 end) total_out,
    sum(amount) balance
from (
    select `Date`, time, @balance carry, amount,
    (@balance := @balance + amount) balance, type,
    @rowNum := IF(`Date` = @prevDate, @rowNum + 1, 1) rowNum,
    @prevDate := `Date`
    from transactions 
    cross join (select @balance := 0) t1
    order by `Date`, time
) t1 group by `Date`

更新:使用自我加入的另一个查询。自联接通常比使用变量慢,但它可能足以满足您的需要。

select t1.date
    coalesce(@prevBalance,0) carry,
    sum(case when t2.type = 'payin' and t2.date = t1.date then t2.amount else 0 end) total_in,
    sum(case when t2.type = 'payout' and t2.date = t1.date then t2.amount else 0 end) total_out,
    sum(t2.amount) balance,
    @prevBalance := sum(t2.amount)
from transactions t1
join transactions t2 on t2.date <= t1.date
group by t1.date
order by t1.date

答案 1 :(得分:1)

我相信你可以通过以下方式得到你的第一个结果:

SELECT date, 
       time, 
       @carry := COALESCE(@carry,0) carry,
       amount,
       @carry := @carry + amount balance, 
       type
  FROM transaction
ORDER BY date, time 

SQL FIDDLE DEMO

答案 2 :(得分:0)

我认为您只需要对除收盘余额之外的所有内容进行汇总查询:

select transaction_date,
       sum(amount) as total,
       substring_index(group_concat(closing_balance order by time desc), ',', 1) as ClosingBalance,
       sum(case when type = 'payin' then amount else 0 end) as deposits,
       sum(case when type = 'payout' then amount else 0 end) as deductions
from transactions
group by transaction_date;

结算余额的逻辑使用技巧来获得当天的最后余额。

答案 3 :(得分:-1)

您可以将您的记录读入数组,然后按日期和时间对它们进行排序并手动求和。需要做很多工作才能完成工作。

    while ($T_row = mysqli_fetch_array($result)) {
        $data[] =  array('TC_Group'=>$TC_Group,'uname'=>$uname);
    }   
    asort($data);
   // process data