Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Optimizar Consulta en Firebird (https://www.clubdelphi.com/foros/showthread.php?t=26719)

AGAG4 01-11-2005 17:33:57

Optimizar Consulta en Firebird
 
Tengo un problema con una consulta en Firebird 1.52, tarda como 10 a 15 mins en generarmela y tengo en la tabla sólo 60,000 registros, el objetivo es de extraer aquellos clientes que han dejado de comprar en cierta sucursal en los últimos 4 meses, muestro la sentencia sql:
Código SQL [-]
select s.sucursal,c.cliente,c.nomcli,c.rfccli,
Sum(c.importeant),Sum(c.importe) from TablaVentas c
join tesp_sucursales s on (s.clave = c.sucursal)
where
  c.sucursal = 1 and
  c.cliente >0 and
  ano=2005 and 
  mes >= 1 and 
  mes < 6 and 
  c.cliente not in 
  (select cliente from TablaVentas 
  where 
    ano=2005 and 
    mes >= 6 and cliente = c.cliente) 
group by s.sucursal,c.cliente,c.nomcli,c.rfccli
order by sum(c.importe) desc
*Tengo como PK los campos Sucursal+Cliente+Ano+Mes todos son de tipo Integer.

Realice varias pruebas entre ellas separar el Subselect y ejecutarlo por separado y se ejecutan al instante, pero por lo que veo si son 60,000 registros obviamente realiza 60,000 busquedas en el subselect es por eso el motivo de que tarda una eternidad, en la pc donde hago pruebas es una P4 con 256 MB en RAM y 20GB en Disco Duro, con WinXP Professional SPII.

Alguna sugerencia de optimizarla, se los agradecería muchisimo.

lpmlpm 01-11-2005 18:09:11

Asi a ojo, y sin tener las tablas para checar te daría estas sugerencias, trata con esta sentencia modificada:

Código SQL [-]
 select s.sucursal,c.cliente,c.nomcli,c.rfccli,
 Sum(c.importeant),Sum(c.importe) from TablaVentas c
join tesp_sucursales s on (s.clave = c.sucursal)
where
  c.sucursal = 1 and
  c.cliente >0 and
  ano=2005 and 
  mes >= 1 and 
  mes < 6 and 
  c.cliente not in 
  (select cliente from TablaVentas 
   where 
     ano=2005 and 
     mes >= 6) 
group by s.sucursal,c.cliente,c.nomcli,c.rfccli
order by sum(c.importe) desc

Quita la relacion del subselect con la consulta principal para que esta
se ejecute una sola vez, y asi creo que el optimizador interno el va a susutituir
la sentencia in por un exists...al hacer la subconsulta única sin necesidad de iterarla
en cada renglon de la consulta primaria debe hacerlo por lo menos un poco mas rápido...

No se si poniendo el sum que tienes en el order by en el select tambien ganes algo...

AGAG4 02-11-2005 00:45:53

Nop
 
Gracias lpmlpm pero no funciono sigue igual no baja de 10 mins. no me quiero imaginar cuando sean 500,000 registros, pero bueno le sigo investigando....

Saludos....

Zeta 02-11-2005 09:02:01

Usás índices?

mejoran mucho la velocidad

Casimiro Notevi 02-11-2005 09:09:40

¿Puedes pasarnos el metadata de la estructura de la base de datos?, así podemos hacer pruebas nosotros.

kalimero 02-11-2005 09:33:56

Hola.

Bueno sin saber como está estructurada la BD te diria que: si solo te interesa saber si ha comprado o no, mira a ver si puedes agrupar por cliente en la subconsulta. Te evitarás así un monton de registros.

saludos

jachguate 03-11-2005 03:02:58

que tal si probas con:

Código SQL [-]
select s.sucursal,c.cliente,c.nomcli,c.rfccli,
       Sum(c.importeant),Sum(c.importe),
       max(c.fecha) MesUltimaCompra
  from TablaVentas c
       inner join tesp_sucursales s on (s.clave = c.sucursal)
 where c.sucursal = 1
   and c.cliente >0
 group by s.sucursal, c.cliente, c.nombli, c.rfccli
having max(c.fecha) < '2005-06-01'

No lo he comprobado, pero debiera mostrarte todos aquellos clientes que no han comprado desde el 1/6/2005.

Hasta luego.

;)

AGAG4 04-11-2005 02:46:51

ok
 
Si tengo 1 indice por Sucursal+Cliente+Ano+Mes, tome estos campos por ser los que dependen después de la instrucción WHERE de los Select's, pero no aumento mucho la velocidad, voy a probar como me comenta jachguate .

Muchas Gracias....

AGAG4 04-01-2006 17:15:49

????
 
Disculpe la tardanza para verificar las pruebas, revise el Select usando Having funciono Bien, pero tengo el problema de que me obliga agrupar por FECHA y me pone 1 mismo cliente varias veces, por lo que lo que yo quiero es agrupar Sólo por clientes, pero si quito dentro del select el Max(c.fecha) no me serviría el having.

Otra cosa que me di cuenta, si pongo lo siguiente:
Código SQL [-]
....
group by cliente,nomcli,rfccli,fecha
having max(fecha)<'01.08.2005'
order by sum(importe) DESC
No me hace el Ordenamiento Descendente, me pone registros revueltos, Ejemplo:
Importe
1200
1000
800
5000
40000
....

Gracias por su sugerencia.

kalimero 04-01-2006 17:39:00

Hola.
Pues entonces agrega la condicion de la fecha en la clausula WHERE
Saludos

AGAG4 04-01-2006 17:48:15

????
 
No puedo agregar dentro del where max(fecha)<'01.08.2005' por si no haz leido quiero aquellos clientes que dejaron de comprar en determinada fecha.

ó Si agrego fecha <='01.08.2005' me obliga a poner un Subselect como arriba lo menciono.

Gracias por su respuesta.

kalimero 04-01-2006 18:02:03

Hola.
No se si entiendo bien lo que dices. Yo me referia a esto.

Código SQL [-]
select s.sucursal,c.cliente,c.nomcli,c.rfccli,
       Sum(c.importeant),Sum(c.importe)
  from TablaVentas c
       inner join tesp_sucursales s on (s.clave = c.sucursal)
 where c.sucursal = 1 and c.fecha < '2005-06-01'
   and c.cliente >0
 group by s.sucursal, c.cliente, c.nombli, c.rfccli

Saludos

AGAG4 04-01-2006 18:19:03

????
 
A como explicas sólo formas un Grupo de clientes que compraron de Enero a Mayo, pero te falta agregar los clientes que compraron de Junio a Diciembre y Sacar el Grupo Final que Compraron de Enero a Mayo pero que NO ESTEN en el Grupo Junio a Diciembre.
No me sirve saber aquellos clientes que SOLO compraron de Enero a Julio.

Espero haberme explicado.

Saludos....

AGAG4 05-01-2006 02:59:47

Resuelto....
 
Hasta ahorita me di cuenta que el Having no es dependiente del Group By por lo tanto quite dentro del Select, Max(c.Fecha) y ya me dio los datos correctos.

Gracias a todos....

Feliz Año 2006.

jachguate 10-01-2006 02:11:30

Lamento entrar hasta ahora y darme cuenta de esto, que ya estaba implicito en la respuesta que te dí hace varios días. Me alegro que todo saliera bien ;)


La franja horaria es GMT +2. Ahora son las 10:55:10.

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