t-sql select получает все месяцы в диапазоне лет - PullRequest
6 голосов
/ 15 ноября 2010

Мне нужно, чтобы выбор возвращал Месяц и год В указанном диапазоне дат, где я бы вводил начальный год и месяц, а выбор возвращал бы месяц и год с даты, которую я ввел до сегодняшнего дня.

Я знаю, что могу сделать это в цикле, но мне было интересно, можно ли сделать это в серии выбирает?

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

и т. Д.

Ответы [ 8 ]

15 голосов
/ 13 февраля 2012

Черт возьми ... использование "подсчета рекурсивного CTE" или "rCTE" так же плохо или хуже, чем использование цикла. Пожалуйста, смотрите следующую статью, почему я так говорю.

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

Вот один из способов сделать это без какого-либо RBAR, включая «скрытый RBAR» подсчитывающего rCTE.

--===== 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
;
3 голосов
/ 15 ноября 2010

Вы можете использовать что-то вроде этого: http://blogs.msdn.com/b/sqlazure/archive/2010/09/16/10063301.aspx

Чтобы сгенерировать эквивалент таблицы чисел, используя диапазоны дат.

Но не могли бы вы уточнить ваши входы и выходы?

Хотите ли вы ввести дату начала, например, '2010-5-1', и дату окончания, например, '2010-8-1', и будет ли она возвращаться каждый месяц между двумя? Вы хотите включить начальный и конечный месяц или исключить их?

Вот некоторый код, который я написал, который будет быстро генерировать инклюзивный результат каждого месяца между двумя датами.

--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#;
2 голосов
/ 22 января 2014

Код ниже генерирует значения для диапазона между 21 июля 2013 и 15 января 2014 . Я обычно использую его в SSRS отчетах для генерации значений поиска для параметра Месяц.

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

Результаты:

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
1 голос
/ 04 сентября 2013
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 голос
/ 05 июня 2011

--- Вот версия, которая получает даты окончания месяца, обычно используемые для целей бухгалтерского учета

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#; 
0 голосов
/ 13 мая 2019

Я знаю, что это старый вопрос, но я слегка испуган сложностью некоторых ответов.Использование CTE, безусловно, является самым простым способом выбора этих значений:

WITH months(dt) AS 
   (SELECT getdate() dt 
    UNION ALL
    SELECT dateadd(month, -1, dt)
    FROM months)
SELECT 
top (datediff(month, '2017-07-01' /* start date */, getdate()) + 1) 
YEAR(months.dt) yr, MONTH(months.dt) mnth
FROM months
OPTION (maxrecursion 0);

Просто наберите любую начальную дату вместо '2017-07-01' выше, и вы можете использоватьэффективное и легко интегрируемое решение.


Редактировать: Ответ Джеффа Модена довольно эффективно выступает против использования rCTE.Тем не менее, в данном случае это, кажется, случай преждевременной оптимизации - мы говорим о десятках записей по всей вероятности, и даже если вы вернетесь к 1900 году с сегодняшнего дня, это все равно незначительный удар.Использование rCTE для обеспечения возможности сопровождения кода, по-видимому, оправдывает себя, если ожидаемый набор результатов мал.

0 голосов
/ 22 августа 2013
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 голосов
/ 15 ноября 2010

вы можете сделать следующее

SELECT DISTINCT YEAR(myDate) as [Year], MONTH(myDate) as [Month]
FROM myTable
WHERE <<appropriate criteria>>
ORDER BY [Year], [Month]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...