SQL - Ayuda con Sum -case por favor

   
Vista:

Ayuda con Sum -case por favor

Publicado por trinidad (12 intervenciones) el 17/04/2015 00:15:09
Hola

Tengo la siguiente inquietud , no he logrado que mi código condicionar si la sumatoria del total del saldo de
los documentos por proveedores si es igual a 0 no los muestre , me pueden ayudar por favor


SELECT t4.baseref 'Documento ', T0.CARDCODE 'Proveedor',CASE
WHEN T3.DebHab = 'D' THEN (T1.Debit-T1.Credit-T3.ReconSum)
WHEN T3.DebHab = 'C' THEN (T1.Debit-T1.Credit+T3.ReconSum)

ELSE (T1.Debit-T1.Credit)
END 'Saldo'

FROM dbo.OCRD T0
INNER JOIN dbo.octg T5 ON T0.GroupNum = T5.GroupNum
INNER JOIN dbo.JDT1 T1 ON T1.ShortName = T0.CardCode
INNER JOIN dbo.OACT T2 ON T2.AcctCode = T1.Account
INNER JOIN dbo.OJDT T4 ON T4.TransId = T1.TransId
LEFT JOIN dbo.Opch Y1 ON Y1.TransId = T1.TransId
LEFT JOIN dbo.ORpc Y2 ON Y2.TransId = T1.TransId
LEFT JOIN dbo.OSLP Y3 ON Y3.SlpCode = Y1.SlpCode OR Y3.SlpCode = Y2.SlpCode

LEFT JOIN (SELECT X0.ShortName 'SN', X0.TransId 'TransId', SUM(X0.ReconSum)'ReconSum', X0.IsCredit 'DebHab', X0.TransRowId 'Linea'
FROM dbo.ITR1 X0
INNER JOIN dbo.OITR X1 ON X1.ReconNum = X0.ReconNum
WHERE X1.ReconDate <= current_timestamp AND X1.CancelAbs = ''
GROUP BY X0.ShortName, X0.TransId, X0.IsCredit, X0.TransRowId) T3 ON T3.TransId = T1.TransId AND T3.SN = T1.ShortName AND T3.Linea = T1.Line_ID

WHERE T0.CardType = 'S' AND T1.RefDate <= current_timestamp AND
(CASE
WHEN T3.DebHab = 'D' THEN (T1.Debit-T1.Credit-T3.ReconSum)
WHEN T3.DebHab = 'C' THEN (T1.Debit-T1.Credit+T3.ReconSum)
ELSE (T1.Debit-T1.Credit)
END) != '0' and

sUM ( CASE T3.DebHab
WHEN'D' THEN (T1.Debit-T1.Credit-T3.ReconSum)
WHEN 'C' THEN (T1.Debit-T1.Credit+T3.ReconSum)

ELSE (T1.Debit-T1.Credit)
END ) != '0'

Group by T0.cardcode , T1.DueDate,T3.DebHab,
T1.Credit,T1.Debit,T3.ReconSum
ORDER BY T0.CardCode



De antemano muchas gracias ,
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Ayuda con Sum -case por favor

Publicado por Leonardo Josué (877 intervenciones) el 17/04/2015 17:06:16
Hola Trinidad:

Tu consulta es bastante complicada y lamentablemente no nos das información acerca de la estructura de tus tablas ni de los datos que almacenas en ellas, por lo tanto, cualquier intento por tratar de ayudarte será jugar al adivino...

Para ti puede resultar muy claro lo que tienes, pero para alguien sin el contexto general resulta imposible, además no dices qué error hay en la consulta, es decir, ¿No te arroja los resultados esperados? bueno, en ese caso comienza por decirnos qué es lo que está regresando la consulta y qué es lo que debería regresar. ¿La consulta te marca algún error? bueno, en ese caso dinos qué error es el que está marcando.

Tampoco mencionas con qué BD's estás trabajando, este dato es muy importante, pues hay diferencias sintácticas muy importantes entre cada uno de ellos.

Comienza desde el principio, dinos qué estructura tiene cada una de tus tablas, pon algunos pocos datos de ejemplo en cada una de ellas y a partir de esos datos dinos qué es lo que esperas obtener como salida, de esta manera será más factible que podamos ayudar.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Sum -case por favor

Publicado por ixchel trinidad brust flores (12 intervenciones) el 17/04/2015 18:25:29
Muchas gracias a todos

Una disculpa , el reporte estoy tratando de realizar son los saldos a pagar

el campo t4.baseref es el numero de documento

el campo t0.cardcode es el codigo del proveedor

con este case

CASE
WHEN T3.DebHab = 'D' THEN (T1.Debit-T1.Credit-T3.ReconSum)
WHEN T3.DebHab = 'C' THEN (T1.Debit-T1.Credit+T3.ReconSum)

ELSE (T1.Debit-T1.Credit)
END 'Saldo'

obtenemos el saldo del proveedor al día

los datos se muestran en este momento así

documento Proveedor saldo

23 a0001 -3000
24 a0001 367
54 a0001 56
456 a0001 2577
234 a0004 677
75 a0005 4000
68 a 0005 -600

Lo que requiero validar es la sumatoria del saldo por proveedor es
decir

proveedor saldo

a0001 0
a0004 677
a0005 3600

si la sumatoria del saldo es diferente de 0 se mostrara la infomacion ,
de esta manera

234 a0004 677
75 a0005 4000
68 a 0005 -600



he tratado de realizar al validación , pero hasta el momento no he obtenido los resultados
deseados

sUM ( CASE T3.DebHab
WHEN'D' THEN (T1.Debit-T1.Credit-T3.ReconSum)
WHEN 'C' THEN (T1.Debit-T1.Credit+T3.ReconSum)

ELSE (T1.Debit-T1.Credit)
END ) != '0'


muchas gracias y saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Sum -case por favor

Publicado por leonardo_josue (877 intervenciones) el 17/04/2015 18:56:15
Hola de nuevo Trinidad:

Insisto en que estás complicando la explicación en lugar de hacerla más sencilla. Trata de simplificad primero el problema y de ahí podemos ir construyendo la consulta que necesitas. Por lo pronto trataré de explicar algo para ver si es más o menos lo que necesitas. Te pedí que nos comentaras con qué BD's estás trabajando, pero no lo hiciste, así es que el ejemplo lo voy a poner en MySQL, para fines de mostrar algo real.

Puedo suponer que en alguna de tus tablas tienes algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> SELECT * FROM documentos;
+--------------+-----------+--------+-------+
| id_documento | Proveedor | DebHab | monto |
+--------------+-----------+--------+-------+
|            1 | a0001     | D      |   100 |
|            2 | a0001     | C      |   100 |
|            3 | a0002     | D      |   200 |
|            4 | a0002     | C      |   100 |
|            5 | a0002     | C      |   100 |
|            6 | a0003     | D      |   200 |
|            7 | a0003     | C      |   100 |
+--------------+-----------+--------+-------+
7 rows in set (0.00 sec)

En tu post no nos dices qué significan las letras D y C... en mi caso, la letra Dsignifica una disposición, compra, o deuda, en otras palabras algo que AUMENTA el saldo para proovedor. en caso contrario la letra C significa en el ejemplo un pago, una devolución o un deposito por parte del proovedor, es decir, algo que DISMINUYE su saldo.

Observa que en todos los casos los montos son positivos, por lo tanto el saldo para un proveedor sería sumar TODOS LOS DOCUMENTOS DE TIPO D y restarles TODOS LOS DOCUMENTOS DE TIPO C.

Observa con los datos que el proveedor a0001 tiene un documento de tipo D por $100 y uno de tipo C también por $100, por lo tanto su saldo es 0. El proveedor a0002 tiene un documento de tipo D por $200 y dos documentos de tipo C, cada uno por la cantidad de $100, por lo tanto su saldo también es cero, sin embargo, el proveedor a0003 tiene un documento de tipo D por $200 y sólo un documento de tipo C por $100, por lo tanto aun tiene un saldo de $100.

Esto podrías calcularlo simplemente así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> SELECT proveedor,
    ->        SUM(CASE debHab WHEN 'D' THEN monto
    ->                        WHEN 'C' THEN -1 * monto
    ->            END) saldo
    -> FROM documentos
    -> GROUP BY proveedor;
+-----------+-------+
| proveedor | saldo |
+-----------+-------+
| a0001     |     0 |
| a0002     |     0 |
| a0003     |   100 |
+-----------+-------+
3 rows in set (0.00 sec)

Observa que en el CASE WHEN simplemente se compara cada uno de los tipo de documento, si es tipo D se SUMA ESA CANTIDAD al saldo, si es de tipo C se RESTA esa cantidad (o lo es es lo mismo, se suma la cantidad NEGATIVA, por eso multiplico por -1)

Finalmente, si sólo quisieras mostrar los saldos mayores a 0, puedes hacerlo de dos maneras, una sería con el HAVING y otra sería con una subconsulta:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> SELECT proveedor,
    ->        SUM(CASE debHab WHEN 'D' THEN monto
    ->                        WHEN 'C' THEN -1 * monto
    ->            END) saldo
    -> FROM documentos
    -> GROUP BY proveedor
    -> HAVING saldo > 0;
+-----------+-------+
| proveedor | saldo |
+-----------+-------+
| a0003     |   100 |
+-----------+-------+
1 row in set (0.00 sec)


o así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> SELECT * FROM
    -> (
    ->   SELECT proveedor,
    ->          SUM(CASE debHab WHEN 'D' THEN monto
    ->                          WHEN 'C' THEN -1 * monto
    ->              END) saldo
    ->   FROM documentos ) T
    -> WHERE saldo > 0;
+-----------+-------+
| proveedor | saldo |
+-----------+-------+
| a0001     |   100 |
+-----------+-------+
1 row in set (0.00 sec)

Espero que esto te pueda servir de algo, si no es así, trata de simplificar tu problema... postea las tablas tal como lo hago al inicio, es decir, algo como esto:

1
2
3
4
5
6
7
8
9
10
11
12
documentos;
+--------------+-----------+--------+-------+
| id_documento | Proveedor | DebHab | monto |
+--------------+-----------+--------+-------+
|            1 | a0001     | D      |   100 |
|            2 | a0001     | C      |   100 |
|            3 | a0002     | D      |   200 |
|            4 | a0002     | C      |   100 |
|            5 | a0002     | C      |   100 |
|            6 | a0003     | D      |   200 |
|            7 | a0003     | C      |   100 |
+--------------+-----------+--------+-------+

y no olvides mencionar con qué BD's estás trabajando.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Sum -case por favor

Publicado por ixchel trinidad brust flores (12 intervenciones) el 17/04/2015 21:16:32
Gracias Leo por tu ayuda

La base que estoy utilizando es SQL SERVER 2012 , los datos pueden ser los que mencionas en la
tabla

documentos;
+--------------+-----------+--------+-------+
| id_documento | Proveedor | DebHab | saldo|
+--------------+-----------+--------+-------+
| 1 | a0001 | D | 100 |
| 2 | a0001 | C | 100 |
| 3 | a0002 | D | 200 |
| 4 | a0002 | C | 100 |
| 5 | a0002 | C | 100 |
| 6 | a0003 | D | 200 |
| 7 | a0003 | C | 100 |
| 8| a0004 | D | 300 |
| 9| a0004 | c | 100 |

+--------------+-----------+--------+-----

Espero poder explicarme ,

Necesito que el query muestre el id_ documento, Proveedor, Saldo
pero si la sumatoria de el saldo es igual a 0 (tal cual comentas : la letra Dsignifica una disposición, compra, o deuda, en otras palabras algo que AUMENTA el saldo para proovedor. en caso contrario la letra C significa en el ejemplo un pago, una devolución o un deposito por parte del proovedor, es decir, algo que DISMINUYE su saldo. )
no debe de mostrar al proveedor

documentos;
+--------------+-----------+--------+-------+
| id_documento | Proveedor | DebHab | saldo |
+--------------+-----------+--------+-------+
| 6 | a0003 | D | 200 |
| 7 | a0003 | C | 100 |
| 8 | a0004 |D | 300 |
| 9| a0004 | c | 100 |
+--------------+-----------+--------+-----


saldo total a0003 d 100
saldo total a0004 d 200

en código creo que seria algo asi


mysql> SELECT id_documento ,proveedor,
-> CASE debHab WHEN 'D' THEN monto
-> WHEN 'C' THEN -1 * monto
-> END 'saldo'
-> FROM documentos
-> group by proveedor
-> having sum ( CASE debHab WHEN 'D' THEN monto
-> WHEN 'C' THEN -1 * monto )> '0'
order by proveedor

Pero no me suma el saldo de todos los documentos del proveedor,

gracias
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Sum -case por favor

Publicado por leonardo_josue (877 intervenciones) el 17/04/2015 22:50:43
Ok, veamos si esto es lo que necesitas, en estos momentos no puedo probar con SQL Server porque no lo tengo instalado en mi equipo, pero debería de funcionar:

Por un lado, partimos de los datos que pones como ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> SELECT * FROM documentos;
+--------------+-----------+--------+-------+
| id_documento | Proveedor | DebHab | monto |
+--------------+-----------+--------+-------+
|            1 | a0001     | D      |   100 |
|            2 | a0001     | C      |   100 |
|            3 | a0002     | D      |   200 |
|            4 | a0002     | C      |   100 |
|            5 | a0002     | C      |   100 |
|            6 | a0003     | D      |   200 |
|            7 | a0003     | C      |   100 |
|            8 | a0004     | D      |   300 |
|            9 | a0004     | C      |   100 |
+--------------+-----------+--------+-------+
9 rows in set (0.01 sec)

El primer paso es hacer la subconsulta que puse arriba, es decir, obtener los proveedores que tienen un saldo mayor a cero:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> SELECT proveedor,
    ->        SUM(CASE debHab WHEN 'D' THEN monto
    ->                        WHEN 'C' THEN -1 * monto
    ->            END) saldo
    -> FROM documentos
    -> GROUP BY proveedor
    -> HAVING saldo > 0;
+-----------+-------+
| proveedor | saldo |
+-----------+-------+
| a0003     |   100 |
| a0004     |   200 |
+-----------+-------+
2 rows in set (0.00 sec)


Ahora, con esta consulta podemos filtrar la tabla de documentos para mostrar sólo aquello que estén dentro de esta lista de proveedores, es decir, hacer esto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> SELECT documentos.*
    -> FROM documentos
    -> INNER JOIN
    -> (  SELECT proveedor,
    ->        SUM(CASE debHab WHEN 'D' THEN monto
    ->                        WHEN 'C' THEN -1 * monto
    ->            END) saldo
    ->    FROM documentos
    ->    GROUP BY proveedor
    ->    HAVING saldo > 0) T
    -> ON documentos.proveedor = T.proveedor;
+--------------+-----------+--------+-------+
| id_documento | Proveedor | DebHab | monto |
+--------------+-----------+--------+-------+
|            6 | a0003     | D      |   200 |
|            7 | a0003     | C      |   100 |
|            8 | a0004     | D      |   300 |
|            9 | a0004     | C      |   100 |
+--------------+-----------+--------+-------+
4 rows in set (0.00 sec)


La única duda que tengo es si el HAVING funciona en SQL Server utilizando el alias, en caso de que no sea así, puedes utilizar la segunda opción que puse, es decir utilizar otra subconsulta.

Haz la prueba y nos comentas.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Ayuda con Sum -case por favor

Publicado por trinidad (12 intervenciones) el 20/04/2015 19:34:44
Hola Buen dia ,

Muchas gracias leo , por tu tiempo y paciencia, ya he avanzado un poco el query ya me muestra
los datos agrupados por proveedor y saldo

este es el código

select T0.cardcode + ' -- ' + Convert(char(40),T0.cardname) 'Proveedor',
SUM (CASE
WHEN T3.DebHab = 'D' THEN (T1.Debit-T1.Credit-T3.ReconSum)
WHEN T3.DebHab = 'C' THEN (T1.Debit-T1.Credit+T3.ReconSum)
ELSE (T1.Debit-T1.Credit)
end ) 'Saldo'


FROM dbo.OCRD T0
INNER JOIN dbo.octg T5 ON T0.GroupNum = T5.GroupNum
INNER JOIN dbo.JDT1 T1 ON T1.ShortName = T0.CardCode
INNER JOIN dbo.OACT T2 ON T2.AcctCode = T1.Account
INNER JOIN dbo.OJDT T4 ON T4.TransId = T1.TransId
LEFT JOIN dbo.Opch Y1 ON Y1.TransId = T1.TransId
LEFT JOIN dbo.ORpc Y2 ON Y2.TransId = T1.TransId
LEFT JOIN dbo.OSLP Y3 ON Y3.SlpCode = Y1.SlpCode OR Y3.SlpCode = Y2.SlpCode

LEFT JOIN (SELECT X0.ShortName 'SN', X0.TransId 'TransId', SUM(X0.ReconSum)'ReconSum', X0.IsCredit 'DebHab', X0.TransRowId 'Linea'
FROM dbo.ITR1 X0 INNER JOIN dbo.OITR X1 ON X1.ReconNum = X0.ReconNum WHERE X1.ReconDate <= current_timestamp AND X1.CancelAbs = ''
GROUP BY X0.ShortName, X0.TransId, X0.IsCredit, X0.TransRowId) T3 ON T3.TransId = T1.TransId AND T3.SN = T1.ShortName AND T3.Linea = T1.Line_ID



WHERE T0.CardType = 'S' AND T1.RefDate <= current_timestamp


Group by T0.cardcode,t0.cardname

having (select SUM (CASE
WHEN T3.DebHab = 'D' THEN (T1.Debit-T1.Credit-T3.ReconSum)
WHEN T3.DebHab = 'C' THEN (T1.Debit-T1.Credit+T3.ReconSum)
ELSE (T1.Debit-T1.Credit)
END)FROM OCRD x
where x.CardCode= t0.CardCode
Group by x.CardCode)!= '0'

ORDER BY T0.CardCode

y los datos los muestra asi

proveedor saldo
a0001 -5799.990000
a0002 -15026.660000
a0003 35156.360000

Lo que no he logrado hasta el momento filtrar a los proveedores ,

+--------------+-----------+--------+-------+
| id_documento | Proveedor | DebHab | monto |
+--------------+-----------+--------+-------+
| 6 | a0003 | D | 200 |
| 7 | a0003 | C | 100 |
| 8 | a0004 | D | 300 |
| 9 | a0004 | C | 100 |

Intente realizarlo con el inner join pero los valores del monto dependen de un left join

existe otra manera de realizar el filtro


saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar