SQL - Consulta a varias tablas

   
Vista:

Consulta a varias tablas

Publicado por Armando (5 intervenciones) el 29/04/2017 20:52:11
Buenas tardes, pf si pueden apoyarme en lo siguiente :

Tengo 3 tablas (Producto, Kardex y Unidades)

Producto:
IdProducto / Nombre / idunidad / saldoinicial
Kardex:
IdProducto / Fecha / Entrada / Salida
Unidades :
Idunidad / Nombre

Necesito un reporte de kardex que me muestre todos los productos de la tabla productos asi no hayan tenido movimiento en el kardex dentro de un rango de fechas que envio como parametro al procedimiento almacenado.

Estructura del Reporte:

IdProducto / Nombre / Saldo Anterior / Entradas / Salidas / Saldo

40 Muebles 10 10 0 20
40 Muebles 10 0 5 15
40 Muebles 10 40 0 55
33 Sillas 20 0 0 20 (este no tuvo movimiento en el mes)
23 Ropero 0 20 0 20]

Como puedo realizar esta consulta, si me apoyan pf.
La estuve haciendo pero cuando doy el rango de fechas los que no tienen movimiento no me salen.

1
2
3
4
select p.idproducto, p.nombre, p.saldoinicial+sum(k.Entradas)-sum(k.Salidas), k.Entrada, k.Salida
left join Kardex k on p.idproducto=k.idproducto
inner join Unidades u on p.idunidad=u.idunidad
where k.Fecha>=@fechainicial and k.Fecha<=@fechafinal

Como ven no tengo el saldo y la consulta no funciona bien.

Agradecere cualquier apoyo sobre el particular.

Armando
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Consulta a varias tablas

Publicado por Jorge (12 intervenciones) el 30/04/2017 03:07:48
para MS-SQL
a ver si entendí

si el producto (en este caso Sillas) no ha tenido movimiento en el mes, pero si ha tenido movimiento en meses anteriores
y quieres que aparezca su saldo final si o si,
entonces la condición where debería ser solamente:
where k.fecha <=@fechafinal

si el producto no ha tenido movimiento nunca, pero tiene su saldo inicial en la tabla producto
y quieres que aparezca en la consulta si o si
entonces se podría incluir el valor NULL en la consulta:
where (k.Fecha>=@fechainicial and k.Fecha<=@fechafinal) OR (k.fecha IS NULL)
pero una vez que el producto tenga movimiento en el kardex, entonces ya no aparecerá (a menos que tenga movimiento en la fecha indicada)

en MS-SQL el código sería así:
1
2
3
4
5
6
7
8
9
10
11
12
select p.idproducto, p.nombre, u.nombre unidad, k.fecha,
       ISNULL(p.saldoinicial,0) SaldoInicial, ISNULL(k.Entrada,0) Entrada, ISNULL(k.Salida,0) Salida,
       ISNULL(p.saldoinicial,0) + ISNULL((k.entrada-k.salida),0) +
       ISNULL((select sum(k2.entrada-k2.salida) Diferencia
               from Kardex as k2
               where k2.idproducto=k.idproducto and k2.fecha<k.fecha),0) SaldoFinal
from Producto as p left join
     Kardex as k on p.idproducto=k.idproducto inner join
     Unidades as u on p.idunidad=u.idunidad
where (k.Fecha>=@fechainicial and k.Fecha<=@fechafinal)
      OR (k.fecha IS NULL)
order by p.Nombre, k.fecha
en MS-SQL uso la función ISNULL porque si el valor es NULL, entonces cualquier operación con Null daría Null,
en lugar de eso lo reemplazo por 0 para que si encuentra null le sume o reste 0 (cero)

el resultado saldría asi:
1
2
3
4
5
6
idproducto	nombre	unidad	fecha	SaldoInicial	Entrada	Salida	SaldoFinal
40		Muebles	Juego	2017-03-02	10	10	0	20
40		Muebles	Juego	2017-03-04	10	0	5	15
40		Muebles	Juego	2017-03-06	10	40	0	55
23		Ropero	Unidad	2017-03-05	0	20	0	20
33		Sillas	Juego	NULL		20	0	0	20
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Consulta a varias tablas

Publicado por Armando (5 intervenciones) el 30/04/2017 08:00:21
Hola, gracias por responder.

Tu interpretacion es casi correcta. Nada mas si nos centramos en el producto Sillas por ejemplo.
Yo necesito mostrar todos los productos esten o no en el kardex, por un rango de fecha que lo envie por parametro como fechainicial y fechafinal.
Aqui puede suceder dos cosas que las Sillas no tengan movimiento en ese rango de fechas, igual tienen que salir, otro que las Sillas tengan movimiento antes de ese rango de fechas, igual tiene que salir pues variara el saldo anterior, otro que las Sillas no s ehayan movido nunca igual tiene que salir.
El campo saldoinicial de un producto puede ser cero o puede tener cantidad.

Probe la consulta, en este producto.
Sillas tiene saldo inicial cero
un movimiento de ingreso en dic/2016 de 30 unidades
coloco la fechainicial=01-01-2017 y fechafinal=31-01-2017
Ejecuto la consulta y no me sale ese producto, cuando deberia salir SaldoAnterior 30 entrada 0 salida 0 saldo 30
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Consulta a varias tablas

Publicado por Jorge (12 intervenciones) el 30/04/2017 19:39:42
en MS-SQL Server
mmmm, una salida rápida podría ser con UNION ALL
quedaría así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
select p.idproducto, p.nombre, u.nombre unidad, k.fecha,
       ISNULL(p.saldoinicial,0) SaldoInicial, ISNULL(k.Entrada,0) Entrada, ISNULL(k.Salida,0) Salida,
       ISNULL(p.saldoinicial,0) + ISNULL((k.entrada-k.salida),0) +
       ISNULL((select sum(k2.entrada-k2.salida) Diferencia
              from Kardex as k2
              where k2.idproducto=k.idproducto and k2.fecha<k.fecha),0) SaldoFinal
from Producto as p left join
     Kardex as k on p.idproducto=k.idproducto inner join
     Unidad as u on p.idunidad=u.idunidad
where (k.Fecha>=@fechainicial and k.Fecha<=@fechafinal)
      OR (k.fecha IS NULL)
 
UNION ALL
 
select p.idproducto, p.nombre, u.nombre unidad, NULL fecha,
       ISNULL(p.saldoinicial,0) SaldoInicial, sum(ISNULL(k.Entrada,0)) Entrada, sum(ISNULL(k.Salida,0)) Salida,
       ISNULL(p.saldoinicial,0)+sum(ISNULL(k.entrada,0)-ISNULL(k.salida,0)) SaldoFinal
from Producto as p left join
     Kardex as k on p.idproducto=k.idproducto inner join
     Unidad as u on p.idunidad=u.idunidad
where (k.Fecha<=@fechainicial)
      AND k.idproducto
      NOT IN (Select k2.idproducto
              from Kardex as k2
              where (k2.Fecha>=@fechainicial and k2.Fecha<=@fechafinal))
group by p.idproducto, p.nombre, u.nombre, p.saldoinicial
order by 2,4

la primera parte muestra todos los movimientos detallados entre las fechas indicadas
incluyendo los que nunca han tenido movimiento en el kardex (OR k.fecha IS NULL)
que aparecerán con fecha NULL

la segunda parte mostraría solo sumatorias (digamos el stock (Saldo Anterior) que hay hasta antes de las fechas de búsqueda)
y que no se encuentren dentro de las fechas indicadas
-que aparecerán con fecha NULL (pero se les podría poner la @fechainicial por ejemplo como informativo que hasta esa
fecha hay ese movimiento)
-el saldo inicial como campo informativo (pero podría ser el SaldoFinal y volverlo a poner en la columna de SaldoFinal otra vez)
-y la sumatoria de entradas y de salidas como campos informativos (pero podría ir en 0 simplemente para que la consulta sea más simple)
-y ordenado por nombre de producto y fecha

dependiendo de la BD SQL en que se trabaje talvez no haya la necesidad de usar tanto ISNULL(,)
pero talvez se pueda hacer con subconsultas anidadas o NOT EXISTS o cosas asi para no usar UNION ALL,
pero son cosas que aún no se usar muy bien :(

Saludos!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar

Consulta a varias tablas

Publicado por Jorge (12 intervenciones) el 30/04/2017 20:45:55
ah, me olvidé de corregir,
en la segunda consulta del Union ALL
dice:
where (k.Fecha<=@fechainicial)

pero debería ser
where (k.Fecha<@fechainicial)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar

Consulta a varias tablas

Publicado por Armando (5 intervenciones) el 01/05/2017 23:26:05
Hola mi estimado, gracias por el apoyo... La consulta me quedo asi...

USE [SF_E_VentasDB]
GO
/****** Object: StoredProcedure [dbo].[pa_rptstockval] Script Date: 01/05/2017 04:32:13 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[pa_rptstockval]
@fechaini date, @fechafin date
-- CONSULTA UNIDA -----
as
(select @fechaini as Fechaini, @fechafin as Fechafin, pro.CodBarras as Codigo,
pro.Descripcion as Articulo,u.Abreviatura as U_Med, pro.UltimoCosto as Costo_Prom,
(isnull(pro.SaldoInicial,0)+ISNULL((select sum(kdx.Entradas-kdx.Salidas) from SF_Tab_Kardex kdx
where kdx.IdProd_TabProductos=pro.IdProd_TabProductos and kdx.Fecha<@fechaini),0)) as SaldoAnterior,
ISNULL(sum(kp.Entradas),0) as Entradas,ISNULL(sum(kp.Salidas),0) as Salidas,
isnull(pro.SaldoInicial,0)+ISNULL((select sum(kdx.Entradas-kdx.Salidas) from SF_Tab_Kardex kdx
where kdx.IdProd_TabProductos=pro.IdProd_TabProductos and kdx.Fecha<=@fechafin),0) as Saldo,
(isnull(pro.SaldoInicial,0)+ISNULL((select sum(kdx.Entradas-kdx.Salidas) from SF_Tab_Kardex kdx
where kdx.IdProd_TabProductos=pro.IdProd_TabProductos and kdx.Fecha<=@fechafin),0))*pro.UltimoCosto as Valorizado
from SF_Tab_Productos pro
left join SF_Tab_Kardex kp on pro.IdProd_TabProductos=kp.IdProd_TabProductos
inner join SF_Tab_Unidades u on pro.IdUnidades_TabUnidades=u.IdUnidades_TabUnidades
where (kp.Fecha>=@fechaini and kp.Fecha<=@fechafin)
or (kp.Fecha IS NULL)
group by pro.CodBarras,pro.Descripcion, u.Abreviatura, pro.UltimoCosto, pro.IdProd_TabProductos, pro.SaldoInicial)
UNION all --- unimos ambas consultas
(select @fechaini as Fechaini, @fechafin as Fechafin, p.CodBarras as Codigo,
p.Descripcion as Articulo,u.Abreviatura as U_Med, p.UltimoCosto as Costo_Prom,
(isnull(p.SaldoInicial,0)+ISNULL((select sum(kdx.Entradas-kdx.Salidas) from SF_Tab_Kardex kdx
where kdx.IdProd_TabProductos=p.IdProd_TabProductos and kdx.Fecha<@fechaini),0)) as SaldoAnterior,
ISNULL(sum(k.Entradas*0),0) as Entradas,ISNULL(sum(k.Salidas*0),0) as Salidas,
ISNULL(p.SaldoInicial,0)+sum(ISNULL(k.Entradas,0)-ISNULL(k.Salidas,0)) as Saldo,
(ISNULL(p.SaldoInicial,0)+sum(ISNULL(k.Entradas,0)-ISNULL(k.Salidas,0)))*p.UltimoCosto as Valorizado
from SF_Tab_Productos p left join
SF_Tab_Kardex k on p.IdProd_TabProductos=k.IdProd_TabProductos inner join
SF_Tab_Unidades u on p.IdUnidades_Tabunidades = u.IdUnidades_TabUnidades
where (k.Fecha<@fechaini) AND
p.IdProd_TabProductos
NOT IN (Select k2.IdProd_TabProductos
from SF_Tab_Kardex as k2
where (k2.Fecha>=@fechaini and k2.Fecha<=@fechafin))
group by p.CodBarras,p.Descripcion, u.Abreviatura, p.UltimoCosto, p.IdProd_TabProductos, p.SaldoInicial)
order by 2,4


Me lista la informacion que necesito, pero si tiende a demorarse un poco, promedio de 25 segundos.
Nuevamente gracias por el apoyo, espero tu opinion a ver que te parece.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar