2010-11-15 16 views
6

Necesito un seleccionar para regresar Mes y año Dentro de un rango de fechas especificado donde ingresaría el año y mes de inicio y el seleccionar regresaría mes y año a partir de la fecha I entrada hasta hoy.t-sql select get all Meses dentro de un rango de años

Sé que puedo hacer esto en un bucle, pero me preguntaba si es posible hacerlo en una serie selecciona?

Year Month 
---- ----- 
2010 1 
2010 2 
2010 3 
2010 4 
2010 5 
2010 6 
2010 7 

y así sucesivamente.

+0

servidor SQL 2008 –

Respuesta

0
declare @date1 datetime, 
    @date2 datetime, 
    @date datetime, 
    @month integer, 
    @nm_bulan varchar(20) 

create table #month_tmp 
    (bulan integer null, keterangan varchar(20) null) 

select @date1 = '2000-01-01', 
     @date2 = '2000-12-31' 

select @month = month(@date1) 

while (@month < 13) 
Begin 
    IF @month = 1 
    Begin 
     SELECT @date = CAST(CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,0,@date1))-1),DATEADD(mm,0,@date1)),111) + ' 00:00:00' as DATETIME) 
    End 
    ELSE 
    Begin 
     SELECT @date = CAST(CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,@month -1,@date1))-1),DATEADD(mm,@month -1,@date1)),111) + ' 00:00:00' as DATETIME) 
    End 
    select @nm_bulan = DATENAME(MM, @date) 

    insert into #month_tmp 
    select @month as nilai, @nm_bulan as nama 

    select @month = @month + 1 
End 

select * from #month_tmp 
drop table #month_tmp 
go 
0

puede hacer lo siguiente

SELECT DISTINCT YEAR(myDate) as [Year], MONTH(myDate) as [Month] 
FROM myTable 
WHERE <<appropriate criteria>> 
ORDER BY [Year], [Month] 
+0

¿Cómo utilizaría los "criterios apropiados" se puede mostrar como ejemplo ... todas las fechas desde 2009-12 hasta la actualidad –

3

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

para generar el equivalente de una tabla de números utilizando rangos de fechas.

¿Pero podría aclarar sus entradas y salidas?

¿Desea ingresar una fecha de inicio, por ejemplo, '2010-5-1' y una fecha de finalización, por ejemplo, '2010-8-1' y hacer que vuelva cada mes entre las 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#; 
+0

Si esto funciona .. –

1

--- Aquí es una versión que se pone la fecha de fin de mes típicamente utilizados para fines contables

DECLARE @StartDate datetime; 
DECLARE @EndDate datetime; 
SET @StartDate = '2010-1-1'; 
SET @EndDate = '2020-12-31'; 
--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(d,-1,DateAdd(m,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#; 
13

gente Gosh ... usando un "recuento de CTE recursiva" 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 manera de hacerlo sin ningún RBAR incluyendo el "RBAR oculto" de un RCTE 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 
; 
+0

Me gusta su método de hacerlo, pero al final todavía no hay RBAR llamando a las funciones AÑO() y MES() en la columna MonthDate? – reverendlarry

+1

Detrás de escena, todo en T-SQL se basa realmente en un bucle de una forma u otra, por lo que todo califica como "RBR". Como yo soy el hombre que acuñó la frase, esto es lo que "RBAR" ha llegado a significar ...RBAR se pronuncia "ree-bar" y es un "Modenism" para "Row By Agonizing Row". El término ha llegado a significar cualquier método de código que requiera más recursos o que provoque ejecuciones más largas debido a su naturaleza fila por fila, incluso si el código es realmente un código "basado en conjunto". Dado que la mayoría de las funciones intrínsecas de SQL Server operan a velocidades de lenguaje de máquina, tendría que decir: "No ... esto no es RBAR". ;-) –

+0

la mejor respuesta aquí – MoreCoffee

1
DECLARE @Date1 DATE 
DECLARE @Date2 DATE 

SET @Date1 = '20130401' 
SET @Date2 = DATEADD(MONTH, 83, @Date1) 

SELECT DATENAME(MONTH, @Date1) "Month", MONTH(@Date1) "Month Number", YEAR(@Date1) "Year" 
INTO #Month 

WHILE (@Date1 < @Date2) 
BEGIN 
    SET @Date1 = DATEADD(MONTH, 1, @Date1) 
    INSERT INTO #Month 
    SELECT DATENAME(MONTH, @Date1) "Month", MONTH(@Date1) "Month Number", YEAR(@Date1) "Year" 
END 

SELECT * FROM #Month 
ORDER BY [Year], [Month Number] 

DROP TABLE #Month 
1

siguiente código genera los valores para el rango entre 21 de Jul 2013 y 15 Ene 2014. Normalmente lo uso en los informes SSRS para generar valores de búsqueda para el parámetro Mes.

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 
Cuestiones relacionadas