Saltar al contenido

t-sql select obtener todos los meses dentro de un rango de años

Solución:

Dios mío … usar un “recursivo CTE” o “rCTE” es tan malo o peor que usar un bucle. Por favor, consulte el siguiente artículo para saber por qué digo eso.

http://www.sqlservercentral.com/articles/T-SQL/74118/

Aquí hay una forma de hacerlo sin ningún RBAR, incluido el “RBAR oculto” de un rCTE de conteo.

--===== Declare and preset some obviously named variables
DECLARE @StartDate DATETIME,
        @EndDate   DATETIME
;
 SELECT @StartDate="2010-01-14", --We'll get the month for both of these 
        @EndDate="2020-12-05"  --dates and everything in between
;
WITH
cteDates AS
(--==== Creates a "Tally Table" structure for months to add to start date
     -- calulated by the difference in months between the start and end date.
     -- Then adds those numbers to the start of the month of the start date.
 SELECT TOP (DATEDIFF(mm,@StartDate,@EndDate) + 1)
        MonthDate = DATEADD(mm,DATEDIFF(mm,0,@StartDate) 
                  + (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1),0)
   FROM sys.all_columns ac1
  CROSS JOIN sys.all_columns ac2
)
--===== Slice each "whole month" date into the desired display values.
 SELECT [Year]  = YEAR(MonthDate),
        [Month] = MONTH(MonthDate) 
   FROM cteDates
;

Puede usar algo como esto: http://blogs.msdn.com/b/sqlazure/archive/2010/09/16/10063301.aspx

Generar el equivalente de una tabla de números usando rangos de fechas.

Pero, ¿podría aclarar sus entradas y salidas?

¿Desea ingresar una fecha de inicio, por ejemplo, '2010-5-1' y fecha de finalización, por ejemplo, '2010-8-1' y ¿volverá todos los meses entre los dos? ¿Desea incluir el mes de inicio y el mes de finalización o excluirlos?

Aquí hay un código que escribí que generará rápidamente un resultado inclusivo de cada mes entre dos fechas.

--Inputs here:
DECLARE @StartDate datetime;
DECLARE @EndDate datetime;
SET @StartDate="2010-1-5 5:00PM";
SET @EndDate = GETDATE();

--Procedure here:
  WITH RecursiveRowGenerator (Row#, Iteration) AS (
       SELECT 1, 1
        UNION ALL
       SELECT Row# + Iteration, Iteration * 2
         FROM RecursiveRowGenerator
        WHERE Iteration * 2 < CEILING(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1))
        UNION ALL
       SELECT Row# + (Iteration * 2), Iteration * 2
         FROM RecursiveRowGenerator
        WHERE Iteration * 2 < CEILING(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1))
     )
     , SqrtNRows AS (
       SELECT *
         FROM RecursiveRowGenerator
        UNION ALL
       SELECT 0, 0
     )
SELECT TOP(DATEDIFF(MONTH, @StartDate, @EndDate)+1) 
       DATEADD(month, DATEDIFF(month, 0, @StartDate) + A.Row# * POWER(2,CEILING(LOG(SQRT(DATEDIFF(MONTH, @StartDate, @EndDate)+1))/LOG(2))) + B.Row#, 0)  Row#
  FROM SqrtNRows A, SqrtNRows B
 ORDER BY A.Row#, B.Row#;

El código siguiente genera los valores para el rango entre 21 julio 2013 y 15 de ene. De 2014. Normalmente lo uso en SSRS informes para generar valores de búsqueda para el parámetro Month.

declare
    @from date="20130721",
    @to date="20140115";

with m as (
select * from (values ('Jan', '01'), ('Feb', '02'),('Mar', '03'),('Apr', '04'),('May', '05'),('Jun', '06'),('Jul', '07'),('Aug', '08'),('Sep', '09'),('Oct', '10'),('Nov', '11'),('Dec', '12')) as t(v, c)),

y as (select cast(YEAR(getdate()) as nvarchar(4)) [v] union all select cast(YEAR(getdate())-1 as nvarchar(4)))

select m.v + ' ' + y.v [value_field], y.v + m.c [label_field]
from m
cross join y
where y.v + m.c between left(convert(nvarchar, @from, 112),6) and left(convert(nvarchar, @to, 112),6)
order by y.v + m.c desc

Resultados:

value_field     label_field
---------------------------
Jan 2014        201401
Dec 2013        201312
Nov 2013        201311
Oct 2013        201310
Sep 2013        201309
Aug 2013        201308
Jul 2013        201307
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *