2010-05-02 14 views
14

que estoy tratando de devolver una lista de cuentas con sus saldos, Resultado de Ingresos yCómo sumar columnas en múltiples condiciones en un GROUP BY

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

Esto es lo que tengo actualmente. ¿Alguien podría explicarme dónde me estoy equivocando?

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] 

ACTUALIZACIÓN

haya corregido los t2 dejó sintaxis de unión de acuerdo con el comentario anterior.

La salida que estoy esperando es obviamente obvia de la pregunta. Para 6 cuentas, el SQL debe devolver 6 cuentas con su Saldo, Ingresos y Resultado de esa cuenta.

¡El problema con el SQL que proporcioné fue que los números son incorrectos! Según los comentarios, creo que el problema se debe a que se unieron varias veces, lo que significa que se suman las cantidades incorrectamente.

+0

¿No debería la unión para TRANSACTION t2 estar en t2 como en t2.ACCOUNT_ID = a.ACCOUNT_ID? {Por favor edita la pregunta. Promovido para comentar a partir de la respuesta de Neil Moss a continuación} – SAMills

Respuesta

17

Como no nos dijo what's going wrong (es decir, describe el comportamiento que obtiene además de describir el comportamiento que espera), es difícil decir dónde, pero hay un par de posibilidades. Neil señala uno. Otra es que, dado que te unes a la tabla de transacciones tres veces, estás combinando transacciones con transacciones y obteniendo repeticiones. En su lugar, únase a la tabla de transacciones una sola vez y cambie la forma en que resume la columna 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] 

Puede utilizar expresiones CASE como una alternativa más legible para las multiplicaciones:

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] 
+0

@outis - AFAIK, t-sql no tiene la función 'LEAST' ni' GREATEST'. – Thomas

+0

@Thomas: bueno, eso apesta. Alterado para no usarlos. – outis

+0

Proporcionó la respuesta final en mi pregunta. Se aceptó su respuesta, sin embargo, se usó SUMA (CASO CUANDO ... para valores de RESULTADO e INGRESOS. – David

6

Quizás quiso decir:

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] 
+0

Acaba de perder el final en la declaración CASE. – David

+0

Upvoted pero no pude aceptar la respuesta ya que mi pregunta era vaga en cuanto a los resultados y solo debería haberse unido a la tabla de transacciones una vez. – David

+0

@David Liddle: Thx se han actualizado. –

1

¿No debería la unión para la transacción T2 ser en t2 como en on t2.ACCOUNT_ID = a.ACCOUNT_ID?

2

No estoy seguro de por qué se necesita el múltiplo une. ¿No podría simplemente hacer algo como:

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]