2017-09-14 1 views
3

私はこのようなテーブルがあります。MYSQL 1つの文で合計列の値と特定の行エントリを選択する方法はありますか。

+-----------+------------+---------------+-------------+--------------+ 
| member_id | balance |  amount | new_balance |  time  | 
+-----------+------------+---------------+-------------+--------------+ 
|   5 |  630 |  -30  |  600  | 2017-08-14 | 
|   3 |  142 |  -68  |  74  | 2017-08-14 | 
|   3 |  120 |  22  |  142  | 2017-08-13 | 
|   3 |  0  |  120  |  120  | 2017-08-12 | 
|  20 |  300 |  324  |  624  | 2017-08-12 | 
|   4 |  100 |  -30  |  70  | 2017-08-11 | 
|   4 |  0  |  100  |  100  | 2017-08-10 | 
|   5 |  30  |  600  |  630  | 2017-08-10 | 
+-----------+------------+---------------+-------------+--------------+ 

をそして私が選択することを期待するようなものである:一定期間内にまとめたものである

+-----------+------------+---------------+---------------+-------------+ 
| member_id | balance | in_amount | out_amount | new_balance | 
+-----------+------------+---------------+---------------+-------------+ 
|   3 |  0 |  142  |  0  |  142  | 
|   4 |  100 |  0  |  -30  |  70  | 
|   5 |  630 |  0  |  0  |  630  | 
|  20 |  300 |  324  |  0  |  624  | 
+-----------+------------+---------------+---------------+-------------+ 

(2017- 2017年8月11日まで08-13)。

残高:期間の開始時の残高。

in_amount:期間内の正の金額の合計。

out_amount:期間内の負の金額の合計。

new_balance:期間終了時の残高。

私は収入と結果を得るために、のような声明をうまくしている:

set @start = "2017-08-11 00:00:00"; 
set @end = "2017-08-13 00:00:00"; 
SELECT 
    DISTINCT(member_id), 
    sum(if(amount>0, amount, 0)) as in_amount, 
    sum(if(amount<0, amount, 0)) as out_amount, 
FROM transaction 
WHERE 
    (time BETWEEN @start and @end) 
group by member_id; 

をしかし、私は声明の中にバランスとnew_balanceを含むようには考えています。誰かが私に何か提案がありますか?

+0

私はメンバー3のためのあなたの出力に従っていません、なぜメンバー5が行方不明ですか? –

+1

サンプルデータのタイムフレームに324のエントリが1つしかない場合、20人が22の結果(流出)を得るにはどうすればよいですか? –

+0

この収入と結果は何ですか?なぜメンバーid 5が期待された結果で拒否されるのですか?バランスを超えた論理は何ですか?あなたに質問してください。 – Shibon

答えて

1

LEFT JOINとともに2つのサブクエリを使用します。

最初のサブクエリは最新の残高を取得します。 2番目のサブクエリは、日付パラメータを使用して、各メンバーの入出金額を合計します。 LEFT JOINを使用して

@start@end間の取引をしなかった者を含む、各メンバーのバランスを得るために私達を可能

set @start = "2017-08-11 00:00:00"; 
set @end = "2017-08-13 00:00:00"; 
select 
    lastTransaction.member_id, 
    lastTransaction.balance, 
    IFNULL(computeInOut.in_amount, 0) as in_amount, 
    IFNULL(computeInOut.out_amount, 0) as out_amount, 
    lastTransaction.balance, 
    -- balance is the most recent balance + computed in amout - computed out amount 
    (lastTransaction.balance + IFNULL(computeInOut.in_amount, 0) + IFNULL(computeInOut.out_amount, 0)) as new_balance 
FROM 
    (-- retrieving the most recent balance information prior to @start 
    SELECT 
     member_id, 
     max(time) as mostRecentTransaction, 
     balance 
    FROM transaction 
    WHERE time <= @start 
    group by member_id 
    ) as lastTransaction 
LEFT JOIN 
    (-- calculating in & out amounts sum based on the date parameters 
    SELECT 
     member_id, 
     sum(if(amount>0, amount, 0)) as in_amount, 
     sum(if(amount<0, amount, 0)) as out_amount 
    FROM transaction 
    WHERE 
     (time BETWEEN @start and @end) 
    group by member_id 
    ) as computeInOut 
ON (lastTransaction.member_id = computeInOut.member_id) 

結果:

+-----------+---------+--------+---------+------------+ 
| member_id | balance | inflow | outflow | newbalance | 
+-----------+---------+--------+---------+------------+ 
|   4 |  100 |  0 |  -30 |   70 | 
|   5 |  30|  0 |  0 |   30 | 
+-----------+---------+--------+---------+------------+ 

メンバー5および20でありますその結果、最初のトランザクションが@startの後に発生したため、イベントに先立って残高がなくなります(11hと13thのトランザクション)

+0

いいです、それは私のために働く。しかし、私は、その期間内に取引記録を持たないメンバーも選択されることを期待しています(私の質問を参照してください、会員5の残高とnew_balanceは変わりません) – user3711105

1

残高フィールドは、期間の開始時または期間の最初の日付のいずれかにすることができるので、limitを持つサブクエリーでこれらを見つけ、合体によって使用するものを決定できます。新しい残高は期間の最後の日付でなければなりません。desc order byとlimitを持つサブクエリーでこれらを見つける必要があります。期間中にイベントがないので

set @start = "2017-08-11 00:00:00"; 
set @end = "2017-08-13 00:00:00"; 
select member_id, 
     coalesce(
     (select t1.balance from t t1 where t1.member_id = t.member_id and t1.dt = @start order by t1.dt desc limit 1) 
     ,(select t1.balance from t t1 where t1.member_id = t.member_id and t1.dt > @start order by t1.dt asc limit 1) 
     ) balance, 
     sum(case when amount > 0 then amount else 0 end) inflow, 
     sum(case when amount < 0 then amount else 0 end) outflow, 
     (select t1.new_balance from t t1 where t1.member_id = t.member_id and t1.dt <= @end order by t.dt desc limit 1) newbalance 
from t 
where t.dt between @start and @end 
group by member_id 

結果

+-----------+---------+--------+---------+------------+ 
| member_id | balance | inflow | outflow | newbalance | 
+-----------+---------+--------+---------+------------+ 
|   3 |  0 | 142 |  0 |  142 | 
|   4 |  100 |  0 |  -30 |   70 | 
|  20 |  300 | 324 |  0 |  624 | 
+-----------+---------+--------+---------+------------+ 
3 rows in set (0.00 sec) 

そして5は脱落します。

関連する問題