web-dev-qa-db-ja.com

GROUP BYの複数の条件で列を合計する方法

残高、結果、収入のあるアカウントのリストを返そうとしています

Account            Transaction
-------            -----------
AccountID          TransactionID
BankName           AccountID
Locale             Amount
Status

これが私が現在持っているものです。誰かが私がどこで間違っているのか説明できますか?

select
    a.ACCOUNT_ID,
    a.BANK_NAME,
    a.LOCALE,
    a.STATUS,
    sum(t1.AMOUNT) as BALANCE,
    sum(t2.AMOUNT) as OUTCOME,
    sum(t3.AMOUNT) as INCOME
from ACCOUNT a
left join TRANSACTION t1 on t1.ACCOUNT_ID = a.ACCOUNT_ID
left join TRANSACTION t2 on t2.ACCOUNT_ID = a.ACCOUNT_ID and t2.AMOUNT < 0
left join TRANSACTION t3 on t3.ACCOUNT_ID = a.ACCOUNT_ID and t3.AMOUNT > 0
group by a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]

[〜#〜]更新[〜#〜]

以下のコメントに従って、t2左結合構文を修正しました。

私が期待している出力は、うまくいけば質問から明らかです。 6つのアカウントの場合、SQLは6つのアカウントと、そのアカウントの残高、収入、結果を返します。

私が提供したSQLの問題は、数値が間違っていることでした!コメントの通り、問題は複数回参加することから生じていると思います。

16
David

何が問題なのか (つまり、予想される動作を説明することに加えて、得られる動作を説明する)を言わなかったので、どこを言うのは難しいですが、いくつかの可能性があります。ニールはそれを指摘している。もう1つは、トランザクションテーブルに3回参加するため、トランザクションとトランザクションをペアにして繰り返しが発生することです。代わりに、トランザクションテーブルで1回結合し、Amount列の合計方法を変更します。

Select
    a.ACCOUNT_ID,
    a.BANK_NAME,
    a.LOCALE,
    a.STATUS,
    sum(t.AMOUNT) as BALANCE,
    sum((t.AMOUNT < 0) * t.AMOUNT) As OUTGOING,
    sum((t.AMOUNT > 0) * t.AMOUNT) As INCOMING
From ACCOUNT a
Left Join TRANSACTION t On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]

乗算のより読みやすい代替としてCASE式を使用できます。

Select
    a.ACCOUNT_ID,
    a.BANK_NAME,
    a.LOCALE,
    a.[STATUS],
    sum(t.AMOUNT) As BALANCE,
    sum(CASE WHEN t.AMOUNT < 0 THEN t.AMOUNT ELSE 0 end) As OUTCOME,
    sum(CASE WHEN t.AMOUNT > 0 THEN t.AMOUNT ELSE 0 end) As INCOME
From ACCOUNT a
Left Join [TRANSACTION] t On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]
22
outis

もしかして:

select 
    a.ACCOUNT_ID, 
    a.BANK_NAME, 
    a.LOCALE, 
    a.STATUS, 
    sum(t1.AMOUNT) as BALANCE, 
    sum(CASE WHEN t2.AMOUNT < 0 THEN t2.Amount ELSE 0 END) as OUTCOME, 
    sum(CASE WHEN t3.AMOUNT > 0 THEN t3.Amount ELSE 0 END) as INCOME 
from 
    ACCOUNT a 
    left join TRANSACTION t1 on t1.ACCOUNT_ID = a.ACCOUNT_ID 
    left join TRANSACTION t2 on t2.ACCOUNT_ID = a.ACCOUNT_ID
    left join TRANSACTION t3 on t3.ACCOUNT_ID = a.ACCOUNT_ID
group by 
    a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS] 
6
Mitch Wheat

複数の結合が必要になる理由がわかりません。あなたは単に次のようなことをすることができませんでした:

Select
    a.ACCOUNT_ID
    , a.BANK_NAME
    , a.LOCALE
    , a.STATUS
    , Sum ( t.Amount ) As Balance
    , Sum( Case When t.Amount < 0 Then Amount End ) As Outcome
    , Sum( Case When t.Amount > 0 Then Amount End ) As Income
From ACCOUNT a
    Left Join TRANSACTION t 
        On t.ACCOUNT_ID = a.ACCOUNT_ID
Group By a.ACCOUNT_ID, a.BANK_NAME, a.LOCALE, a.[STATUS]
3
Thomas

TRANSACTION t2の結合は、on t2.ACCOUNT_ID = a.ACCOUNT_IDのようにon t2である必要があります

1
Neil Moss