tornillos |
500 |
01/01/2009 |
tornillos |
-50 |
02/01/2009 |
tornillos |
-200 |
04/01/2009 |
tornillos |
-220 |
10/01/2009 |
tornillos |
500 |
11/01/2009 |
tornillos |
-100 |
20/01/2009 |
Si en este escenario nos pidiesen obtener la cantidad máxima de tornillos que llegó a haber en el almacén podrían ponernos en un pequeño apuro. La idea sería conseguir una tercera columna con la cantidad en stock y poder seleccionar el máximo. El problema de eso es que necesitamos de alguna manera recorrer la tabla fila a fila, pero claro, dicen por ahí que eso de los cursores es cosa mala….
tornillos |
500 |
01/01/2009 |
500 |
tornillos |
-50 |
02/01/2009 |
450 |
tornillos |
-200 |
04/01/2009 |
250 |
tornillos |
-220 |
10/01/2009 |
30 |
tornillos |
500 |
11/01/2009 |
530 |
tornillos |
-100 |
20/01/2009 |
430 |
He aquí un método alternativo a la utilización de los cursores para obtener la columna “agregado” y poder seleccionar el máximo stock, que tiene lugar el 11 de enero con un valor de 530 tornillos.
1º) Creamos una tabla temporal con los registros que nos interesan, ordenándolos por orden cronológico
2º) Recorremos un bucle que analice la primera fila y la eliminamos, de esta forma podemos recorrer la tabla completa.
Veámoslo en el ejemplo:
–Creamos la tabla del ejemplo. Para simplificar introducimos solo los
–datos que utilizaremos, pero esto no afecta al ejemplo
declare @movimientos as table
(Producto nvarchar(10), Cantidad int, Fecha date)
insert into @movimientos values (‘tornillos’,500,‘20090101’)
insert into @movimientos values (‘tornillos’,-200,‘20090104’)
insert into @movimientos values (‘tornillos’,-50,‘20090102’)
insert into @movimientos values (‘tornillos’,-220,‘20090110’)
insert into @movimientos values (‘tornillos’,500,‘20090111’)
insert into @movimientos values (‘tornillos’,-100,‘20090120’)
–Definimos una tabla temporal, con la misma estructura que la original
declare @tmp as table
(Producto nvarchar(10), Cantidad int, Fecha date)
–Introducimos aquí los datos que nos interesen, ordenados convenientemente
insert into @tmp
select * from @movimientos
where Producto=‘tornillos’
order by fecha asc
–Variables auxiliares que utilizaremos
declare @Acc int,@Max int
set @Acc=0 –Valor acumulado hasta la fila actual
set @Max=0 –Valor máximo hasta la fila actual
–Esta instrucción elimina de la ventana de mensajes el recuento de filas afectadas
set nocount on
–Mientras exista alguna fila en @tmp recorro el bucle
While(Exists(select * from @tmp))
BEGIN
–Sumamos la 1ªfila al acumulado
select top(1) @Acc=@Acc+Cantidad from @tmp;
–Eliminamos la 1ª fila; ya está computada
delete top(1) from @tmp;
–Comprobamos si el acumulado es máximo
if(@Acc>@Max)
set @Max=@Acc;
print @Acc;
END
print »
print ‘Máximo alcanzado:’
print @Max
Lo que nos devuelve por pantalla la columna de acumulados y el máximo stock que llegó a haber en el almacén:
500
450
250
30
530
430
Máximo alcanzado:
530
La pega de este método son la cantidad de deletes que utiliza, así que en el siguiente post tocará un método alternativo (sin cursores, of course) más eficaz.
gracias !!!
Buen post, sólo una cosa sobre las tablas temporales por si puede aclararar, no es lo mismo tablas temporales que variables de tipo table, aunque se puedan usar de manera similar:
Tablas temporales:
http://technet.microsoft.com/es-es/library/ms177399.aspx
Variables tipo table:
http://technet.microsoft.com/es-es/library/ms175010.aspx
Por otro lado, la carga de la tabla temporal también se podría hacer aprovechando un SELECT INTO para la creación y la seleción a la vez:
http://technet.microsoft.com/es-es/library/ms190750%28SQL.90%29.aspx
Saludos!
Gracias por la aclaración José: debería de cuidar un poco más el lenguaje por si alguien se confunde con las variables y las verdaderas tablas temporales, aunque en este ejemplo no sea relevante.
Y sí, en efecto el select into nos ayudaría, aunque lo dejé así a propósito para el siguiente post, donde quiero añadir más columnas a la tabla.