diciembre 13, 2012

Primer y ultimo dia en el Año/Mes en SQL Server

Vamos a recorrer del 1 al 12 que equivalen a las doce meses del año, y para cada mes, del año especificado (en este ejemplo: el actual)  obtendremos la fecha inicio del mes, que sabemos que siempre es el dia 1ro. y en base a esta fecha obtendremos la fecha fin del año/mes, que ésta si es variable por el mes de febrero que puede tener 28 ó 29 dias de acuerdo al año ó 30 o 31 días para otros meses y con estas fechas podremos hacer un query a nuestra para obtener valores de acuerdo a un rango de fechas entre: Fecha Inicio (1er dia del año/mes)  y Fecha Fin (ultimo dia del año/mes).

Espero les sea util! son 2 objetos a crear en este ejemplo: una función scalar y el script que utiliza un while de Transact-SQL con apoyo de una tabla variable para almecenar los resultados.

1. Creamos la función que obtiene la ultima fecha del mes:
-- =============================================
-- Author:        Julio C Soria
-- Description:    obtener el ultimo dia del mes a determinada fecha.
-- ojo tiene que ser en el formato aaaaMMdd
-- Select dbo.fncObtenerUltimoDiaMes ( '20121001')
-- =============================================
create FUNCTION [dbo].[fncObtenerUltimoDiaMes]
(
    @Fecha smalldatetime
)
RETURNS smalldatetime
AS
BEGIN
   

  declare @d varchar(2),@m varchar(2),@a varchar(4), @FE varchar(50) , @FI varchar(50) , @FN varchar(50),@FcF varchar(50),
  @DiaFinMes  smalldatetime
  
    --//recupera el dia ctual 
    set @d=day(@Fecha) 
    --//recupera el mes actual 
    set @m=month(@Fecha) 
    --//recupera el año actual 
    set @a=year(@Fecha) 
    --//fecha dada por el sistema 
    set @FE=@d + '/' + @m + '/' + @a 
    --//Primer dia del Mes 
    set @FI='01' + '/' + @m + '/' + @a 
    --//Ultimo dia del mes 
    set @FN=dateadd( month,1,@FI) -1 
    --//Ultimo dia del mes en formato dd/mm/yyyy 
    set @FcF=cast(day(@FN)as varchar) + '/' + cast(month(@FN)as varchar) + '/' + cast(year(@FN)as varchar) 
     
  
   set @DiaFinMes = convert(smalldatetime, @FcF)

    -- Return the result of the function
    RETURN @DiaFinMes

END

2. Creamos el quiery en transact-SQL para recorrer cada mes y obtener la Fecha Inicio y Fecha Fin de cada mes, para poder pasarlas como parametros a nuestro where de nuestra tabla que tiene una fecha por ejemplo de venta y poder asi obtener las suma del importe de ventas por mes:

--Recorrer cada mes y obtener fecha correspondiente al 1er dia del mes y fecha correspondiente al ultimo dia del mes.
 
declare
@ContadorMes tinyint, @año numeric(5,0),
@FechaInicioMes smalldatetime, @FechaFinMes smalldatetime
   
--Declaracion de la variable tabla
declare @TablaVarMesImportePNI
TABLE (
Mes tinyint NOT NULL,
ImporteMes money  NOT NULL
   
)
set @año = YEAR(getdate())
set @ContadorMes = 1--enero

--iterar por cada mes del año ,para obtener el importe
while @ContadorMes < 13
begin
    --contruir fechia dia 1ro del mes que itera
    SET @FechaInicioMes = CASE
        WHEN @ContadorMes = 1 THEN convert(char(4), @año) + '01' + '01'
        WHEN @ContadorMes = 2 THEN convert(char(4), @año) + '02' + '01'
        WHEN @ContadorMes = 3 THEN convert(char(4), @año) + '03' + '01'
        WHEN @ContadorMes = 4 THEN convert(char(4), @año) + '04' + '01'
        WHEN @ContadorMes = 5 THEN convert(char(4), @año) + '05' + '01'
        WHEN @ContadorMes = 6 THEN convert(char(4), @año) + '06' + '01'
        WHEN @ContadorMes = 7 THEN convert(char(4), @año) + '07' + '01'
        WHEN @ContadorMes = 8 THEN convert(char(4), @año) + '08' + '01'
        WHEN @ContadorMes = 9 THEN convert(char(4), @año) + '09' + '01'
        WHEN @ContadorMes = 10 THEN convert(char(4), @año) + '10' + '01'
        WHEN @ContadorMes = 11 THEN convert(char(4), @año) + '11' + '01'
        WHEN @ContadorMes = 12 THEN convert(char(4), @año) + '12' + '01'
       
    END
   
   
    --obtenemos ultimo dia del mes, que  en febrero puede variar de acuerdo al año
    Select @FechaFinMes = dbo.fncObtenerUltimoDiaMes (convert(smalldatetime,@FechaInicioMes))
   
    --poblar en la tabla var
    insert into @TablaVarMesImportePNI
    select @ContadorMes, @ContadorMes
     --aqui iria el query a la tabla para filtrar por FI y FF
    --Select @ContadorMes, isnull(SUM(Importe),0)
    --from Tabla1
    --Where Fecha between  @FechaInicioMes and @FechaFinMes 
   
    set @ContadorMes = @ContadorMes + 1
end

--la salida en pantalla del resultado en la tabla variable.
select
MesNombre = CASE
    WHEN Mes = 1 THEN 'ENERO'
    WHEN Mes = 2 THEN 'FEBRERO'
    WHEN Mes = 3 THEN 'MARZO'
    WHEN Mes = 4 THEN 'ABRIL'
    WHEN Mes = 5 THEN 'MAYO'
    WHEN Mes = 6 THEN 'JUNIO'
    WHEN Mes = 7 THEN 'JULIO'
    WHEN Mes = 8 THEN 'AGOSTO'
    WHEN Mes = 9 THEN 'SEPTIEMBRE'
    WHEN Mes = 10 THEN 'OCTUBRE'
    WHEN Mes = 11 THEN 'NOVIEMBRE'
    WHEN Mes = 12 THEN 'DICIEMBRE'
END,
ImporteMes
From @TablaVarMesImportePNI