Re: Consulta compleja

From: Oswaldo Hernández <listas(at)soft-com(dot)es>
To: Jorge Vidal Martinez <jvm(at)utenet(dot)com(dot)ar>
Cc: Ricardo Fuentes Pereira <rfuentesp(at)gmail(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Consulta compleja
Date: 2005-06-01 10:01:49
Message-ID: 429D878D.2000008@soft-com.es
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Ricardo,

No te compliques e intenta hacer las cosas de forma sencilla:

Es este caso no puedes hacer un left join directo de las tablas porque
los movimientos se multiplican.

Para que esto no suceda tienes que agrupar cada tabla antes de unirlas,

Mi consejo es que definas una view para cada una, asi tendras tambien
mas flexibilidad para usarlas desde otras consultas.

create or replace view total_compra_rut as
select
c.rut,
sum( coalesce(c.valor_neto * (1 + c.valor_iva), 0) ) as importe
from
sx_fact_compra as c
group by
c.rut;

create or replace view total_gasto_rut as
select
g.rut,
sum( coalesce(g.valor_neto * (1 + g.valor_iva), 0) ) as importe
from
sx_fact_gasto as g
group by
g.rut;

Ahora solo tienes que hacer un join normalito uniendo los proveedores
con las views:

select
prov.rut,
prov.nombre,
--- si uno de los proveedores no tiene compa o gasto será nulo
coalesce(compras.importe, 0) + coalesce(gastos.importe, 0) as
total_valor

from
sx_prov as prov,
left join
total_compra_rut as compras
on prov.rut = compras.rut
left join
total_gasto_rut as gastos
on prov.rut = gastos.rut
where
--- esta clausula evita que se muestren proveedores sin movimiento
(compras.rut is not null or gastos.rut is not null)
--- filtro de provedores, no poner para que salgan todos
and prov.rut = 'el proveedor que quieras'
;

Revisa la sintaxis puesto que no esta probado.

---> OJO con las combinaciones de sum() y coalesce() <---
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
La expresion:
'colesce(sum(valor),0)'

primero hace el sum() y luego evalua el resultado de este con coalesce,
por lo que si uno de los valores que pasan al sum es un nulo el
resultado final será = 0.

La espresion correcta es:
'sum(coalesce(valor, 0))'

de esta forma aseguras que no entra en sum ningun valor nulo.

Suerte.

--
*****************************************
Oswaldo Hernández
oswaldo(at)soft-com(dot)es
*****************************************

Jorge Vidal Martinez escribió:
> Ricardo:
> Efectivamente, hace esto
>
> .......rut ....... | .nombre..| num_fact |.......rut ....... |
> valor_neto | valor_iva | num_fact | rut | valor_neto |
> valor_iva
> -------------+----------+---------+--------------+-----------+---------+----------+-------------+-----------+---------
>
> 11111111-1 | Ricardo .| ............1 | 11111111-1 | 150 |
> 0.19 | 1 | 11111111-1 | 100 | 0.19
> 11111111-1 | Ricardo .| ............1 | 11111111-1 | 150 |
> 0.19 | 2 | 11111111-1 | 200 | 0.19
> 11111111-1 | Ricardo .| ............2 | 11111111-1 | 250 |
> 0.19 | 1 | 11111111-1 | 100 | 0.19
> 11111111-1 | Ricardo .| ........... 2 | 11111111-1 | 250 |
> 0.19 | 2 | 11111111-1 | 200 | 0.19
> 22222222-2 | Andres | ............3 | 22222222-2 | 50 |
> 0.19 |
> 22222222-2 | Andres | ............4 | 22222222-2 | 300 |
> 0.19 |
>
> rut | nombre | sum_valor
> ------------+---------+-----------
> 11111111-1 | Ricardo | 1666 - Erroneo - cuando tiene facturas de
> compras y de gastos hace N * N.
> 22222222-2 | Andres | 416.5 - Bien - porque solo tiene valores
> en una tabla.
>
> Perdon, otra oportunidad
>
> SELECT AA.rut, AA.nombre , AA.valor1 + BB.valor2
> FROM ( SELECT A.rut, A.nombre, ( COALESCE(SUM(B.valor_neto * (1 +
> B.valor_iva)), 0) as valor1
> FROM sx_prov A LEFT JOIN
> sx_fact_compra B ON A.rut = B.rut
> GROUP BY A.rut, A.nombre ) AA LEFT JOIN
> ( SELECT rut ,COALESCE(SUM(valor_neto * (1 + valor_iva)),
> ) AS valor2
> FROM fact_gasto
> GROUP BY rut ) BB on AA.rut = B.rut
>
>
>
> ---- Original Message ----- From: "Ricardo Fuentes Pereira"
> <rfuentesp(at)gmail(dot)com>
> To: "Jorge Vidal Martinez" <jvm(at)utenet(dot)com(dot)ar>
> Cc: <pgsql-es-ayuda(at)postgresql(dot)org>
> Sent: Tuesday, May 31, 2005 10:49 AM
> Subject: Re: [pgsql-es-ayuda] Consulta compleja
>
>
>> Jorge Vidal Martinez escribió:
>>
>>> Ricardo, estas totalizado las las sx_fact_compra y las sc_fact_gastos
>>> por RUC y luego al hacer join con las facturas y agruparlas por un
>>> atributo de esta tabla te repite este total como tantas facturas tengas.
>>>
>>> Intenta
>>>
>>> SELECT
>>> A.ruc, A.nombre ,
>>> ( COALESCE(SUM(B.valor_neto * (1 + B.valor_iva)), 0) +
>>> COALESCE(SUM(C.valor_neto * (1 +C. valor_iva)), 0) ) AS sum_valor
>>> FROM
>>> sx_prov prov A
>>> LEFT JOIN
>>> sx_fact_compra B ON A.rut = B.rut
>>> LEFT JOIN
>>> sx_fact_gasto C ON A.rut = C.rut
>>> GROUP BY
>>> A.ruc, A.nombre
>>>
>>> El LEFT te devuelve todas las tuplas que esten en la tabla primaria
>>> esten o no en la secundaria..
>>>
>>> Por lo que los proveedores que no tengan facturas de Compras o
>>> Gastos, te aparecen en el resultado.
>>>
>>> Saludos
>>> Jorge
>>>
>> Hola. Gracias por responder.
>> Lo probé, pero para los sgtes datos:
>> test=# select * from sx_prov;
>> rut | nombre
>> ------------+---------
>> 11111111-1 | Ricardo
>> 22222222-2 | Andres
>> (2 filas)
>>
>> test=# select * from sx_fact_compra;
>> num_fact | rut | valor_neto | valor_iva
>> ----------+------------+------------+-----------
>> 1 | 11111111-1 | 150 | 0.19
>> 2 | 11111111-1 | 250 | 0.19
>> 3 | 22222222-2 | 50 | 0.19
>> 4 | 22222222-2 | 300 | 0.19
>> (4 filas)
>>
>> num_fact | rut | valor_neto | valor_iva
>> ----------+------------+------------+-----------
>> 1 | 11111111-1 | 100 | 0.19
>> 2 | 11111111-1 | 200 | 0.19
>> (2 filas)
>>
>> me devuelve
>>
>> test=# SELECT
>> test-# A.rut, A.nombre ,
>> test-# ( COALESCE(SUM(B.valor_neto * (1 + B.valor_iva)), 0) +
>> test(# COALESCE(SUM(C.valor_neto * (1 +C. valor_iva)), 0) ) AS
>> sum_valor
>> test-# FROM
>> test-# sx_prov A
>> test-# LEFT JOIN
>> test-# sx_fact_compra B ON (A.rut = B.rut)
>> test-# LEFT JOIN
>> test-# sx_fact_gasto C ON (A.rut = C.rut)
>> test-# GROUP BY
>> test-# A.rut, A.nombre ;
>> rut | nombre | sum_valor
>> ------------+---------+-----------
>> 11111111-1 | Ricardo | 1666
>> 22222222-2 | Andres | 416.5
>> (2 filas)
>>
>> Lo cual es erroneo para el caso del rut 11111111-1 pues debiera ser
>> 833, como si es correcto con mi otra consulta (ver mail anterior)
>>
>> Saludos.
>>
>>
>>
>> ---------------------------(fin del mensaje)---------------------------
>> TIP 3: si publicas/lees desde Usenet, por favor envía "subscribe-nomail"
>> a majordomo(at)postgresql(dot)org para que tus mensajes puedan llegar
>> a los suscriptores de la lista
>>
>>
>>
>> --
>> No virus found in this incoming message.
>> Checked by AVG Anti-Virus.
>> Version: 7.0.322 / Virus Database: 267.3.3 - Release Date: 31/05/2005
>>
>>
>
>
> ---------------------------(fin del mensaje)---------------------------
> TIP 6: ¿Has buscado en los archivos de nuestra lista de correo?
>
> http://archives.postgresql.org/pgsql-es-ayuda
>

In response to

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Victor Lopez 2005-06-01 10:18:46 Re: cambiar una tabla de esquema
Previous Message Maritza Parra 2005-06-01 08:57:18 Problemas con libpq