Ver Mensaje Individual
  #11  
Antiguo 17-01-2009
Bpascal Bpascal is offline
Miembro
 
Registrado: ene 2009
Posts: 14
Reputación: 0
Bpascal Va por buen camino
Hola,

Ok, me tomé un tiempito para leer detenidamente el querry original de los insumos y creo que tengo claro que es lo que hace.

Principalmente tienes 2 tablas, INSUMOS es la tabla maestra donde estan los codigos, descripciones etc de los productos, y la tabla INVENTARIOS donde estan los movimientos de los productos tanto de entrada como de salida, la cual se diferencia por el campo tipo; "I" significa ingreso y "E" significa egreso.

La meta es basicamente listar todos los codigos de INSUMOS con su saldo en unidades y valores resumidos desde la tabla INVENTARIOS, el resumen se puede condicionar por ejemplo de que solo sea de determinada empresa, bodega o incluso solo incluyendo hasta determinada fecha si se quiere, etc.


En tu querry tu estas haciendo a la tabla de movimientos (que por naturaleza es grande) lo siguente:

- 2 veces SELECT para obtener el data saldo en unidades
- 2 veces SELECT para obtener el dato saldo en valores
- 4 veces select par obtener el dato de costo unitario.

En total 8 selects por la cada codigo de la tabla insumos, la cual tu dices tiene aprox 1000 registros, esto genera que se le apliquen aproximadamente 8,000 selects a una tabla llamada inventario que seguramente tiene 20 mil o 30 mil y creciendo por que son las transaciones.

Vemos como podemos bajar un poco la cantidad de SELECTS aplicados.

-----------------------------

Primero dejame explicarte el uso de INNER JOIN para relacionar 2 tablas, realmente es bien simple:

La tabla INVENTARIOS tiene el campo "bodega" que es el numero Id de una bodega
tambien tiene el campo "empresa" que es el numero Id de una empresa

Tienes una tabla llamada BODEGA la cual tiene su campo "ID", su campo "empresa", y su campo "nombre"

Si dedeas generar un listado de la tabla inventarios incluyendo una columna que diga el nombre de la bodega tu lo haces de la siguiente manera:

Cita:
SELECT
I.id, I.cantidad, I.tipo, I.empresa I.bodega, B.nombre
FROM
INVENTARIO I, BODEGA B
WHERE
I.empresa=B.empresa AND I.bodega = B.id
Ahora re-escrito el querry usando INNER JOIN seria:
Cita:
SELECT
I.id, I.cantidad, I.tipo, I.empresa I.bodega, B.nombre
FROM
INVENTARIO I
INNER JOIN BODEGA B ON I.empresa=B.empresa AND I.bodega = B.id
El resultado es exactamente lo mismo, unicamente se ha quitado la seecion WHERE y la condicion se movio a la seccion INNER JOIN.

Ahora tu te preguntaras "y que?, si es lo mismo entonces cual es la ventaja de hacerlo con WHERE ó hacerlo con INNER JOIN ?"

Usar inner join te permite liberar el WHERE de las condiciones utilizadas para enlazar tablas, muchas veces es necesario utilizar 4 o 5 tablas al mismo tiempo y obtener informacion de ellas, escribir un WHERE donde estan todas esas relaciones mas las condiciones que son para selecionar los registros deseados harian un where ya muy complicado. Utiliza la clausula WHERE solo para escribir las condiciones que se requieren para seleccionar los registros deseados en la tabla principal; y utiliza la clausula INNER JOIN para especificar la relacion que hay entre las tablas involucradas, esto ayuda al SQL a saber la mejor manera de utilizar los indices de las tablas para hacer la relacion.
------------------------------

Ok, ahora a continuacion te paso a como haria yo el querry que genere el listado en discucion;

Yo primero resumiria la tabla de inventarios utilizando UN tan solo SELECT creando una tabla temporal, esto reducira drasticamente la cantidad de select con tantas condiciones. De hecho la maneras mas optimia seria 2 tablas temporales, una por las entradas y otra por las salidas pero no quiero hacerte mas largo el post:

Cita:
SELECT
id,tipo,SUM(cantidad) AS cantidad, sum(cantidad * precio * tc) as valor
FROM
Inventario I
INNER JOIN BODEGA B ON (I.bodega = B.id) and (I.empresa = B.empresa)
GROUP BY
I.id,I.tipo
WHERE
I.empresa=:numempresa AND B.nombre=:nombrebedega
INTO
#TEMP_Table
Ok, un tan solo SELECT que me genera una tabla donde ya estan resumidas las cantidades y los valores por codigo de producto y por movimiento, es decir hay tan solo un registro de cada codigo por todas las "E" y uno por todas la "I". en el where puedes agregar mas condiciones como de rango de fechas por ejemplo.

Ahora hagamos otro querry para generar el listado final enlazando la tabla INSUMOS y la tabla #temp_table:

Cita:
SELECT
m.cod_insum,M.nom_insum, m.unidad, M.CRITICO, m.rotacion,
(SELECT t.cantidad from #Temp_table T WHERE t.id = m.cod_insumo AND t.tipo='I') -
((SELECT t.cantidad from #Temp_table T WHERE t.id = m.cod_insumo AND t.tipo='E') as saldo,
(SELECT t.valor from #Temp_table T WHERE t.id = m.cod_insumo AND t.tipo='I') -
((SELECT t.valor from #Temp_table T WHERE t.id = m.cod_insumo AND t.tipo='E')
as valor_saldo
Ok, aqui se ve que hay 4 SELECTS, sin envargo estos son aplicados a una tabla drasticamente reducida y las condiciones utilizadas son tribiales. Si se utilizan 2 tablas temporales una para entradas y otros para salidas entonces se reduciria a 2 SELECTS.

---------------------------------------------

Te recomiendo que le des una ojeada a la informacion sobre tablas temporales, estas se borran solas cuando se cierra la sesion, pero deveras borralas manualmente mientras la seccion este activa antes de hacer una siguiente consulta porque el SELECT INTO fallará cuando encuentre que ya hay una tabla temporal con ese nombre.


saludos.

Última edición por Bpascal fecha: 17-01-2009 a las 23:52:36.
Responder Con Cita