miércoles, 6 de octubre de 2010

SQL Server: Diversion con getdate() y otras funciones bizarras

Creo que hoy me siento algo geek, por eso voy a publicar algunas cosas que ayudarian a mas de uno en lo que se refiere a elaboracion de queries con SQL Server... aunque con un poco de esfuerzo estas mismas pueden portarse a DB2, Oracle, MySQL u otros manejadores de bases de datos que cuenten con algun dialecto de SQL, asi que saquen lapiz y papel que la catedra dara comienzo:

1) Obtener datos en un rango de fechas de una semana: La teoria detras de esto es la siguiente: Supongamos que nuestra Base de Datos (BD) tiene una tabla donde almacenamos los pedidos de clientes y queremos agrupar lo que se ordeno esta semana y la semana pasada Sin importar que dia se corra el query. Habitualmente mas de alguno respondera que con datepart(ww,[campo fecha])-1 bastaria para sacar la semana pasada pero... que ocurriria si corres el query la primer semana de Enero en la cual datepart devuelve 1? El resultado obvio es que tendrias la semana 0!!! Ahora, suponiendo que el primer dia de la semana sera el domingo y el ultimo el sabado entonces algo asi nos puede servir:

declare @domingo as datetime, @sabado as datetime

--Usar la funcion CONVERT y le agregamos el codigo de formato 101 para eliminar la hora de la fecha, getdate() trae ambas cosas y no se pueden separar.
set @domingo=convert(varchar(10),getdate()+(1-datepart(dw,getdate())),101)

set @sabado=convert(varchar(10),getdate()+(7-datepart(dw,getdate())),101)

--Supongamos que la tabla se llama "ordenes"
with lasordenes(fecha,cliente,parte,cantidad) as (
select fecha,cliente,parte,cantidad from ordenes where fecha between @domingo and @sabado --Esta semana
union all
select fecha,cliente,parte,cantidad from ordenes where fecha between @domingo-7 and @sabado-7
--La semana Pasada
)select * from lasordenes order by fecha desc

2) Desplegar la informacion del ejemplo anterior en columnas: Ahora, si quieren una columna con las ordenes de esta semana y las de la semana pero sin incluir fechas, solo numeros de parte, asi es como podrias hacerlo:

declare @domingo as datetime, @sabado as datetime


--igual que antes, le quitamos la hora a la fecha set @domingo=convert(varchar(10),getdate()+(1-datepart(dw,getdate())),101)
set @sabado=convert(varchar(10),getdate()+(7-datepart(dw,getdate())),101)



--Se usa sum() porque no sabemos que fechas puedan venir ademas no es requerido saberlo

select cliente,parte,
sum(case when fecha between @domingo and @sabado then cantidad else 0 end) as [esta semana],
sum(case when fecha between @domingo-7 and @sabado-7 then cantidad else 0 end) as [semana pasada]
from ordenes where fecha between @domingo-7 and @sabado
group by cliente,parte



Estos ejemplos pueden ser de mucha utilidad cuando se requiere manejar lapsos de tiempo, la teoria es bastante simple, para calcular el rango de fechas de una semana siempre que comience en domingo y concluya en sabado entonces hacemos lo siguiente:

* Conocer el dia de la semana actual, para eso usamos datepart(dw,fecha). Aqui obtendremos un numero segun el dia de la semana, domingo=1, lunes=2, etc. (aqui hay mas info sobre como funciona datepart)

*Para saber la fecha del domingo de esta semana, efectuamos la siguiente operacion: fecha de hoy + (1-resultado de datepart(dw,fecha de hoy)), para dejar esto mas claro prueba el siguiente estatuto:

--El resultado es 2010-10-03 18:52:19.617 suponiendo que la fecha actual es 2010-10-06 18:52:19.617
select getdate()+(1-datepart(dw,getdate()))

*Para el sabado la operacion es parecida: fecha de hoy + (7-resultado de datepart(dw,fecha de hoy)), el ejemplo siguiente demuestra los resultados:

--El resultado es 2010-10-09 18:54:40.820 suponiendo que la fecha actual es 2010-10-06 18:54:57.820
select getdate()+(7-datepart(dw,getdate()))


*Ahora a estos resultados les agregamos o sumamos dias segun lo que se requiera, generalmente serian 7 dias para movernos de las fechas de una semana a la otra.

No hay comentarios.:

Publicar un comentario