Query sin cursores...Ayuda!!!!

18/07/2008 - 13:22 por hamil1978 | Informe spam
Hola amigos.

En una tabla tengo la siguiente informacion

Tabla: Movimientos
Articulo Empresa Fecha Cantidad
M07033 is 2007-06-29 9
M07033 is 2007-07-13 4
M07033 is 2007-08-03 3
M07033 is 2007-12-31 5
M07033 is 2008-02-29 12
M07033 is 2008-03-06 20
M07033 is 2008-04-24 19

Para una intervalo de fechas 2008-05-03 y 2008-05-05, por ejemplo
genero una tabla Stock, para lo cual tengo que calcular el Stock a la
Fecha.

Tabla: Stock
Articulo Empresa Fecha Stock_Fecha
M07033 is 2008-05-03 19
M07033 is 2008-05-04 19
M07033 is 2008-05-05 19

De la tabla movimientos tomaría el inmediato inferior a la fecha del
stock, en este caso el valor 19 (2008-04-24).

Con cursores almacenaria los valores de la tabla Stock, y luego al
recorrer realizaría una comparación con la tabla movimientos y
obtendria el valor inferior inmediato a la fecha, pero es demasiado
lento mi cursor por lo que pido su ayuda.

Gracias amigos

Preguntas similare

Leer las respuestas

#1 Carlos M. Calvelo
18/07/2008 - 15:03 | Informe spam
Hola amigo,

On 18 jul, 13:22, wrote:
Hola amigos.

En una tabla tengo la siguiente informacion

Tabla: Movimientos
Articulo Empresa Fecha Cantidad
M07033 is 2007-06-29 9
M07033 is 2007-07-13 4
M07033 is 2007-08-03 3
M07033 is 2007-12-31 5
M07033 is 2008-02-29 12
M07033 is 2008-03-06 20
M07033 is 2008-04-24 19

Para una intervalo de fechas 2008-05-03 y 2008-05-05, por ejemplo
genero una tabla Stock, para lo cual tengo que calcular el Stock a la
Fecha.

Tabla: Stock
Articulo Empresa Fecha Stock_Fecha
M07033 is 2008-05-03 19
M07033 is 2008-05-04 19
M07033 is 2008-05-05 19

De la tabla movimientos tomaría el inmediato inferior a la fecha del
stock, en este caso el valor 19 (2008-04-24).

Con cursores almacenaria los valores de la tabla Stock, y luego al
recorrer realizaría una comparación con la tabla movimientos y
obtendria el valor inferior inmediato a la fecha, pero es demasiado
lento mi cursor por lo que pido su ayuda.




Entiendo que se tiene que hacer un join de todas las combinaciones
(Articulo, Empresa) con todas las fechas en el rango.

Para eso creamos primero esta función que puede generar un
rango de fechas:

-
CREATE function Fechas(@mindate datetime, @maxdate datetime)
returns @fechas TABLE (fecha datetime, diasemana int)
as
begin
while @mindate <= @maxdate
begin
insert into @fechas (fecha,diasemana)
values (@mindate, (datepart(dw, @mindate)+@@datefirst)%7)
set @mindate = @mindate + 1
end
return
end

Suponiendo ahora que tenemos el rango de fechas en las variables
@fecha_inico y @fecha_final, puedes probar esta consulta:


declare @fecha_inicio datetime, @fecha_final datetime

set @fecha_inicio = '20080503'
set @fecha_final = '20080505'
SELECT
M1.Articulo,
M1.Empresa, F.Fecha ,
ISNULL(
(SELECT TOP 1 Cantidad
FROM Movimientos
WHERE Articulo=M1.Articulo AND
Empresa=M1.Empresa AND
Fecha <= F.Fecha
ORDER BY Fecha DESC
),0) AS Stock_Fecha
FROM
(SELECT DISTINCT Articulo, Empresa FROM Movimientos) M1
CROSS JOIN
dbo.Fechas(@fecha_inicio,@fecha_final) F
-

En vez de la función Fechas(...) puedes usar también una tabla
que puedes generar a partir de la función. Eso sería mas
eficiente.

Saludos,
Carlos
Respuesta Responder a este mensaje
#2 hamil1978
20/07/2008 - 00:37 | Informe spam
Gracias Carlos, me sirvio de mucho tu ayuda.

PERO, tu que eres experto en SQL, a la consulta lo he agragado otro
campo IMPORTE, en el TOP 1, quiero sacar la cantidad y el importe y
tengo este error:

Msg 116, Level 16, State 1, Line 6
Sólo se puede especificar una expresión en la lista de selección
cuando la subconsulta no se especifica con EXISTS.

Se que es muy facil para tí, ayudame por favor, te estare muy
agradecido, funciona muy rapido ahora, nada que ver con los cursores.



Saludos Carlos


SELECT
M1.Articulo,
M1.Empresa, F.Fecha ,
ISNULL(
(SELECT TOP 1 Cantidad,Importe
FROM Movimientos
WHERE Articulo=M1.Articulo AND
Empresa=M1.Empresa AND
Fecha <= F.Fecha
ORDER BY Fecha DESC
),0) AS Stock_Fecha
FROM
(SELECT DISTINCT Articulo, Empresa FROM Movimientos) M1
CROSS JOIN
dbo.Fechas(@fecha_inicio,@fecha_final) F
-
Respuesta Responder a este mensaje
#3 Carlos M. Calvelo
20/07/2008 - 10:50 | Informe spam
Hola,

On 20 jul, 00:37, wrote:
Gracias Carlos, me sirvio de mucho tu ayuda.

PERO, tu que eres experto en SQL, a la consulta lo he agragado otro
campo IMPORTE, en el TOP 1, quiero sacar la cantidad y el importe y
tengo este error:

Msg 116, Level 16, State 1, Line 6
Sólo se puede especificar una expresión en la lista de selección
cuando la subconsulta no se especifica con EXISTS.

Se que es muy facil para tí, ayudame por favor, te estare muy
agradecido, funciona muy rapido ahora, nada que ver con los cursores.

Saludos Carlos

SELECT
M1.Articulo,
M1.Empresa, F.Fecha ,
ISNULL(
(SELECT TOP 1 Cantidad,Importe
FROM Movimientos
WHERE Articulo=M1.Articulo AND
Empresa=M1.Empresa AND
Fecha <= F.Fecha
ORDER BY Fecha DESC
),0) AS Stock_Fecha
FROM
(SELECT DISTINCT Articulo, Empresa FROM Movimientos) M1
CROSS JOIN
dbo.Fechas(@fecha_inicio,@fecha_final) F
-



Puede que te haya servido mi ayuda pero creo que está mal. Entiendo
ahora que lo que en realidad quieres son todos los movimientos entre
dos fechas y para aquellas fechas para las que no existe ningún
movimiento quieres añadir una linea como referencia al 'último'.

Si es así, entonces la consulta que te he dejado tiene dos problemas.
Uno es que si para el mismo artículo y la misma empresa existe mas de
un movimiento con la misma fecha, la consulta que te he dado solo
te dejará ver uno de ellos. Otro probema es que en ese caso tampoco
es posible determinar qué movimiento es el 'último'.

Espero haber interpretado bien ahora tu problema. Si es así pon aquí
la estructura de la tabla movimientos (con CREATE TABLE), y no te
olvides de especificar la clave primaria. Si se sabe cual es la clave
primaria podremos forzar un orden total (para así poder escoger sin
ambigüedades el 'último' movimiento) entre aquellos movimientos que
tienen la misma empresa, el mismo artículo y la misma fecha.

Por si no entiendes esta historieta. Mira este ejemplo:

Articulo Empresa Fecha Cantidad Importe
M07033 is 2007-06-29 9 5,00
M07033 is 2007-06-29 9 3,00
M07033 is 2007-06-29 3 4,00

Como ves los registros no se puede diferenciar solo con la
combinación {Artículo, Empresa, Fecha}.

Qué cantidad va con la fecha 2007-06-29?
Pues bien, al azar podemos escoger 9.

Eso es lo ya estamos haciendo mal ahora, porque no verás con la
consulta que tambien hay otro 9 y un 3.

Ahora, que Importe van en esa fecha? Escogamos 4,00 al azar.
Podemos escoger 5,00 que sí vá con el 9. Pero, por qué no 3,00?

Quieres entonces ver esto ...

Articulo Empresa Fecha Cantidad Importe
M07033 is 2007-06-29 9 4,00

... como resultado? Me parece que no.

La próxima vez que ejecutes la misma consulta con los mismos datos
puede que te dé otra respuesta.

Saludos,
Carlos
Respuesta Responder a este mensaje
#4 hamil1978
20/07/2008 - 14:48 | Informe spam
Hola Carlos, gracias por tu apreciación.
Esta es la tabla donde registro los movimientos ingresos a almacen,
cada movimiento como llave primaria es el Nro_Movimiento
(1,2,3,4,5...). La query, gracias a tu ayuda lo he tenido que colocar
un SUM(Cantidad) porque puede darse el caso que haya ingresos para el
mismo articulo y misma empresa en el mismo día.

Movimiento Empresa Articulo Fecha Cantidad Importe
1 is M07033 29/06/2007 9,00 90
2 is M07033 13/07/2007 4,00 40
3 is M07033 03/08/2007 3,00 30
4 is M07033 31/12/2007 5,00 50
5 is M07033 29/02/2008 12,00 120
6 is M07033 06/03/2008 20,00 200
7 is M07033 24/04/2008 9,00 90
8 is M07033 24/04/2008 4,00 40
9 as M07033 13/07/2007 4,00 40
10 as M07033 03/08/2007 7,00 70
11 as M07033 31/12/2007 7,00 70
12 is M07033 29/02/2008 7,00 70

Teniendo en cuanta estos datos, por ejemplo para el conjunto
(M07033,is, 200805039 tendria como cantidad 13 que esw la suma del
inmediato inferior al 200805039, que es la suma de los movimientos de
las fechas 20080424.

M07033 is 2008-05-03 00:00:00.000 13.000000000000

Me parece que con el SUM se peude solucionar el problema, lo que tengo
que tomar si no hay movimientos para esa fecha dada es el inmediato
inferior y si hay varios movimientos a esa fecha los tengo que suma.

Este es el codigo con el SUM con el cual me ayudaste. Mi pregunta
ahora es, como incluyo la suma del importe, no se donde incluir el
EXISTS????.

declare @fecha_inicio datetime, @fecha_final datetime

set @fecha_inicio = '20080503'
set @fecha_final = '20080505'
SELECT
M1.Articulo,
M1.Empresa, F.Fecha ,
ISNULL(
(SELECT TOP 1 sum(Cantidad)
FROM Movimientos
WHERE Articulo=M1.Articulo AND
Empresa=M1.Empresa AND
Fecha <= F.Fecha
GROUP BY Articulo,Fecha
ORDER BY Fecha DESC
),0) AS Stock_Fecha
FROM
(SELECT DISTINCT Articulo, Empresa FROM Movimientos) M1
CROSS JOIN
dbo.Fechas(@fecha_inicio,@fecha_final) F
ORDER BY Empresa

Gracias Carlos
Respuesta Responder a este mensaje
#5 hamil1978
20/07/2008 - 15:14 | Informe spam
Hola Carlos, este es el codigo al final que he logrado que funcione
con tu ayuda.
No se si hay forma de optimizar los SUM, colocar algo como
SUM(Cantidad), SUM(Importe) simplemente.

Saludo Carlos


declare @fecha_inicio datetime, @fecha_final datetime

set @fecha_inicio = '20080503'
set @fecha_final = '20080505'
SELECT
M1.Articulo,
M1.Empresa, F.Fecha ,
ISNULL(
(SELECT TOP 1 sum(Cantidad)
FROM Movimientos
WHERE Articulo=M1.Articulo AND
Empresa=M1.Empresa AND
Fecha <= F.Fecha
GROUP BY Articulo,Fecha,Empresa
ORDER BY Fecha DESC
),0) AS Stock_Fecha,
ISNULL(
(SELECT TOP 1 sum(importe)
FROM Movimientos
WHERE Articulo=M1.Articulo AND
Empresa=M1.Empresa AND
Fecha <= F.Fecha
GROUP BY Articulo,Fecha,Empresa
ORDER BY Fecha DESC
),0) AS Importe_Fecha

FROM

(SELECT DISTINCT Articulo, Empresa FROM Movimientos) M1
CROSS JOIN
dbo.Fechas(@fecha_inicio,@fecha_final) F
ORDER BY Empresa
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida