Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Optimizar StoreProcedure Resumen de Cuenta (https://www.clubdelphi.com/foros/showthread.php?t=89126)

adripugliesso 30-09-2015 13:35:17

Optimizar StoreProcedure Resumen de Cuenta
 
Buenos dias tengo un Store Procedure que arma un resumen de cuentas de proveedores calculando Debe, Haber y Saldo. El problema es que cuando existen muchos registros de un proveedor esta consulta tarda 10 a 20seg en responder o a veces mas. Lo que hace la consulta es ir calculando el saldo restando el total de haber - total de debe en cada registro.


Código SQL [-]
SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, S.fecha)) as Fecha, S.percIIBB, S.PercGcias,
  S.idMovimiento, ISNULL(S.idMovCampo, 0) as idMovCampo, S.importe, S.Neto, S.idOP,
  S.Empresa, S.idProveedor,  S.NroComprobante, S.idTipoMov, S.idOrigenPago, S.idEmpresa,
  S.Tipo, S.TipoLetra, S.NroLote, S.NroFact, S.Detalle, S.Vehiculo, S.Debe, S.Haber,

  ((SELECT (F.Facturas - P.pagos - CASE WHEN ch.Saldo is NULL THEN 0 ELSE ch.Saldo END) as SAldo FROM

  (SELECT (CASE WHEN SUM(Importe) IS NULL THEN 0 ELSE SUM(Importe) END) as Facturas FROM Movimientos
  WHERE
  idProveedor = @paramidProveedor
  AND
  idTipoMov = 1
  AND
  idMovimiento < s.idMovimiento) as F,

  (SELECT (CASE WHEN SUM(Importe) IS NULL THEN 0 ELSE SUM(Importe) END) as Pagos FROM Movimientos M1
  WHERE
  M1.idProveedor = @paramidProveedor
  AND
  ((idTipomov = 5) OR (idTipomov = 3) OR (idTipomov = 6) OR (idTipomov = 7))
  AND
  M1.idMovimiento < s.idMovimiento) as P,

  (Select SUM(Monto) as Saldo FROM 
  Cheques C INNER JOIN Movimientos M
  ON M.idMovimiento = C.idMov 
  WHERE 
  M.idProveedor =  @paramidProveedor
  AND
  C.idMov < s.idMovimiento) as Ch) + s.Debe - s.Haber 
  
  ) as Saldo 
  
  FROM 

  (SELECT fecha ,  percIIBB, PercGcias, idMovimiento, idmovcampo, Importe, neto,
    idOP, E.Nombre as Empresa, idProveedor, NroComprobante, idTipoMov, idOrigenPago,
    M.idEmpresa, TC.Tipo, TipoLetra, NroLote, NroFact, Detalle, Vehiculo,
    Importe as Debe, 0 as Haber
  FROM Movimientos M INNER JOIN TipoComprobante TC
  ON M.idTipoComp = TC.idComprobante   LEFT JOIN Empresas E
  ON M.idEmpresa = E.idEmpresa
  WHERE
  idProveedor = @paramidProveedor
  AND
  idTipomov = 1
  
  UNION

  SELECT M.fecha , M.percIIBB, M.PercGcias, M.idMovimiento, idmovcampo, Importe,
         neto, idOP, E.Nombre as Empresa, M.idProveedor, NroComprobante, M.idTipoMov,
         M.idOrigenPago, M.idEmpresa, TC.Tipo, TipoLetra, NroLote, NroFact, M.Detalle,
         M.Vehiculo, 0 as Debe, M.Importe + (CASE WHEN (Select SUM(Monto)
  FROM Cheques WHERE idMov = M.idMovimiento) IS NULL THEN 0
       ELSE (Select SUM(Monto) FROM Cheques WHERE idMov = M.idMovimiento) END) as Haber
  FROM Movimientos M INNER JOIN TipoComprobante TC
  ON M.idTipoComp = TC.idComprobante LEFT JOIN Empresas E
  ON M.idEmpresa = E.idEmpresa
  WHERE
  M.idProveedor = @paramidProveedor
  AND
  ((idTipomov = 5) OR (idTipomov = 3) OR (idTipomov = 6) OR (idTipomov = 7))
  GROUP BY M.fecha , M.percIIBB, M.PercGcias, M.idMovimiento, idmovcampo, E.Nombre,
           M.idProveedor, NroComprobante, M.idTipoMov, M.idOrigenPago, M.idEmpresa,
           TC.Tipo, TipoLetra, NroLote, NroFact, M.Detalle, M.Vehiculo, M.Importe,
           M.Neto, M.idOP
  ) as S 

WHERE S.idMovimiento >= @paramDesde
  AND S.idMovimiento <= @paramHasta
  AND S.Detalle LIKE '%'+@paramDetalle+'%'
ORDER BY idMovimiento

hay alguna manera mas eficiente de ir armando un resumen de cuentas ???

fjcg02 30-09-2015 16:45:43

Vaya lío....
con qué motor trabajas?

Saludos

adripugliesso 30-09-2015 16:51:24

SQL Server 2005. No me interesa por ahi corregir el codigo de programacion, sino la logica. O sea cual es la mejor forma para armar un resumen de cuentas con Debe - Haber - Saldo con un Store Procedure SQL..

gaunmanuel 01-10-2015 02:10:26

Definitivamente es un query enorme.
Si tu problematica es el tiempo que tarda, te recomiendo que la consulta la analices con la herramienta DataBase Engine Tuning Advisor, la encuentras en el menu Herramientas del Management Studio.
Esta herramienta lo que detectara es si te faltan algunos indices en las tablas que manejas y te recomendara generarlos, y esto hara que tu consulta sea mas rápida.


saludos.

fjcg02 01-10-2015 08:38:17

La semana pasada respondí a una pregunta parecida, y la repuesta fue "divide y vencerás". Al final era un campo por el que se ordenaba y que no tenía índice.

Divide las querys tal y como te recomiendan y mide los tiempos. Revisa el plan de ejecución e identifica qué queries se ejecutan lentas para revisar los índices o la posible mejora de la consulta.

Un saludo


La franja horaria es GMT +2. Ahora son las 23:27:43.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi