Re: Consulta con saldo de la fila anterior

From: Gabriel Hermes Colina Zambra <hermeszambra(at)yahoo(dot)com>
To: "Arturo Munive \[pgsql-es-ayuda\]" <arturomunive(at)gmail(dot)com>, Postgresql <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: Consulta con saldo de la fila anterior
Date: 2007-12-31 15:30:02
Message-ID: 380946.67745.qm@web63710.mail.re1.yahoo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda


--- "Arturo Munive [pgsql-es-ayuda]"
<arturomunive(at)gmail(dot)com> escribió:

> Abro este nuevo hilo con una idea para solucionar un
> problema que surgió
> de otro.
>
> Se tiene una tabla con movimientos de salida y
> entrada de productos y se
> queiere una consulta que arroje resultados de este
> tipo
>
> Mov Entrada Salida Saldo
> 01 10 0 10
> 02 20 0 30
> 03 0 5 25
> 04 15 0 40
> 05 0 12 28
>
> donde el valor saldo de la segunda línea es Saldo de
> la linea
> anterior+entrada de la segunda
> es decir 10+20 = 30
>
> donde un valor de columna en una linea depende de un
> valor en otra
> columna de la anterior
>
> Al asunto puede resolverse con subconsultas pero
> como gabriel indicaba
> en el otro hilo con la acumulación de datos se hace
> lento
>
> Alguna solución, tablas auxiliares funciones
> "mágicas"
>
> Si alguno de ustedes ya resolvio un problema similar
> pueden delinearnos
> como asi puedo sacar la mejor solucion derivada de
> mi analisis y la
> experiencia suya.
>
> Gracias
> --
> TIP 5: ¿Has leído nuestro extenso FAQ?
>
> http://www.postgresql.org/docs/faqs.FAQ.html
>
Arturo tengo 3 metodos para eso y conozco 4.

Metodo uno dos views iguales y una sub consulta

"central"."cmovimientos_stock1"
"central"."cmovimientos_stock"

Metodo dos, con un alias y la misma operacion
"central"."cmovimientos_stock1"

Ahi te pongo la DDL de una de ellas y la forma en que
la invoco.

Dos contras, primero no lee la linea anterior, por
cada linea hace un sum de las anteriores. y para
desplegar una ficha en 2400000 cabezales y 500000
lineas tenes una demora de 2 minutos y algo.

CREATE OR REPLACE VIEW "central"."cmovimientos_stock"
(
id_local,
sucursal,
inventario,
id_empresa,
empresa,
categoria_empresa,
id_lin,
documento,
serie,
numero,
fecha,
id_articulo,
entradas,
salidas,
precio_u)
AS
SELECT cabezales.id_local, locales.descripcion AS
sucursal,
tipo_documentos.inventario, cabezales.id_empresa,
cempresas.empresa,
cabezales.categoria_empresa, documentos.id_lin,
tipo_documentos.documento,
cabezales.serie, cabezales.numero,
cabezales.fecha, documentos.id_articulo,
CASE WHEN ((tipo_documentos.stock_cantidad)::text
= '+'::text) THEN
documentos.cantidad ELSE (0)::double precision END
AS entradas, CASE WHEN
((tipo_documentos.stock_cantidad)::text =
'-'::text) THEN
documentos.cantidad ELSE (0)::double precision END
AS salidas, CASE WHEN
((tipo_documentos.stock_cantidad)::text =
'+'::text) THEN (documentos.cif *
cabezales.cotizacion) ELSE
(documentos.precio_venta_unitario *
cabezales.cotizacion) END AS precio_u
FROM ((central.tipo_documentos JOIN
((central.cempresas JOIN central.cabezales
ON (((cempresas.categoria_empresa =
(cabezales.categoria_empresa)::text)
AND (cempresas.id_empresa =
cabezales.id_empresa)))) JOIN
central.documentos ON ((cabezales.id_cab =
documentos.id_cab))) ON
((tipo_documentos.id_documentos =
cabezales.id_documentos))) JOIN
central.locales ON ((locales.id_local =
cabezales.id_local)))
WHERE (((tipo_documentos.stock_cantidad)::text =
'+'::text) OR
((tipo_documentos.stock_cantidad)::text =
'-'::text))
ORDER BY cabezales.fecha, documentos.id_articulo,
documentos.id_lin,
tipo_documentos.documento;

Llamada a la ficha

select central.cmovimientos_stock.id_local,
central.cmovimientos_stock.sucursal,
central.cmovimientos_stock.inventario,
central.cmovimientos_stock.id_empresa,
central.cmovimientos_stock.empresa,
central.cmovimientos_stock.categoria_empresa,
central.cmovimientos_stock.id_lin,
central.cmovimientos_stock.documento,
central.cmovimientos_stock.serie,
central.cmovimientos_stock.numero,
central.cmovimientos_stock.fecha,
central.cmovimientos_stock.id_articulo,
central.cmovimientos_stock.entradas,
central.cmovimientos_stock.salidas,
(select
sum(coalesce(entradas,0)-coalesce(salidas,0))
from central.cmovimientos_stock1 where
id_articulo=
central.cmovimientos_stock.id_articulo and
(fecha<central.cmovimientos_stock.fecha or
(fecha=central.cmovimientos_stock.fecha
and id_lin<central.cmovimientos_stock.id_lin)))
as saldo,
central.cmovimientos_stock.precio_u from
central.cmovimientos_stock
where central.cmovimientos_stock.id_articulo='100'
order by id_articulo,fecha,id_lin

Metodo 3
Simplemente llenar la grilla de la consulta y dejar
vacio el saldo, llenando esta consulta por programa, o
sea resolverlo en el recordset o control del cliente.

Metodo 4 usar una funcion pl/pgsql que llame a la
consulta y genere un recordset con el saldo y lo
devuelva con setof.

Metodo 5 vistas materializadas, este metodo me fue
sugerido pero no lo probe aun.

Metodo 6, crear la tabla tipo vista materializada,
pero llenarla en el momento de la consulta con una
funcion pl/pgsql que recorra el select con loop donde
tenga un contador nsaldo por ejemplo y llenar la tabla
con insert, este metodo me resulto muy bien en saldos
de acreedores y deudores donde tengo incluso un if
para determinar si paso un parametro con el codigo que
quiero o con un cero se lo aplico a todos los codigos.

Con este metodo baje la consulta de 50 segundos a 0.20
ms.

Y por ahora es el que me resulta mas conveniente.

Ahora la linea anterior creo que no es posible en
postgresql, puesto que creo no tener un
previous.saldo+entrada-salida as saldo

Bueno Arturo, en este punto tengo una buena curva de
experiencia, desde el primer metodo que me sirvio
hasta que crecio el volumen de informacion, hasta este
ultimo donde creo que puedo multiplicar por 10 los
registros que hoy tengo y la performance seria igual a
la rapides de un balazo.

Suerte y feliz 2008 para todos

____________________________________________________________________________________
¡Capacidad ilimitada de almacenamiento en tu correo!
No te preocupes más por el espacio de tu cuenta con Correo Yahoo!:
http://correo.espanol.yahoo.com/

In response to

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Alvaro Herrera 2007-12-31 17:01:43 Re: Depurar Funciones step to step.
Previous Message Arturo Munive 2007-12-31 13:49:40 Re: Depurar Funciones step to step.