简体   繁体   中英

Create list of dates, a month apart, starting from current date

I'm looking for a simple select query (not using a table) to just return a list of dates, 1 month apart. The output should looke something like this, (assuming GetDate() = '2011-07-05 11:59:000' and I wanted between NOW() and NOW()+4 months

Date
2011-07-05 11:59:000
2011-08-05 11:59:000
2011-09-05 11:59:000
2011-10-05 11:59:000
2011-11-05 11:59:000

The part that's killing me is calculating the next year, for example if i run this query in Nov, the months should be listed as 11, 12, 1, 2. Thanks!

You can use recursive CTE and need not string UNIONs together if the requirement is not fixed as below:

 ;with MonthlyCalendar as (
 select cast(getdate() as datetime) as dt
 union all
 select dateadd(mm, 1, dt)
 from MonthlyCalendar
) 
select top 5 dt as [Date] from MonthlyCalendar
option (maxrecursion 0) 

When it comes to performance and you have the need for only 4 months above UNION is far superior than recursive option.

I prefer to handle these small (one off) situations by looping through the data and building the list based on the current (or target) date:

if object_id('tempdb..#dates') is not null drop table #dates
select dateadd(MINUTE, -1, CONVERT(VARCHAR(10), dateadd(DD, 1, getdate()), 111)) result into #dates

declare @current datetime
select @current = result from #dates

while not exists (select * from #dates where result = dateadd(month, 4, @current))
  begin
    insert into #dates
    select dateadd(month, 1, max(result)) from #dates
  end

select * from #dates order by result

@JNK's answer, just reworked to give you each date in a row:

SELECT GETDATE() 'Date'
UNION
SELECT DATEADD(month, 1, GETDATE()) 'Date'
UNION
SELECT DATEADD(month, 2, GETDATE()) 'Date'
UNION
SELECT DATEADD(month, 3, GETDATE()) 'Date'
UNION
SELECT DATEADD(month, 4, GETDATE()) 'Date'

Had to do something like this just this morning!

SELECT GETDATE(),
       DATEADD(month, 1, GETDATE()),    
       DATEADD(month, 2, GETDATE()),
       DATEADD(month, 3, GETDATE()),
       DATEADD(month, 4, GETDATE())

DATEADD takes care of all that year consideration logic for you, and leap years and such too.

Obviously this returns a list of columns. See Ryan's answer for the row solution!

try this:

DECLARE @intFlag INT
declare @LastLimit as int
set @LastLimit = 4
SET @intFlag = 0
WHILE (@intFlag <@LastLimit)
BEGIN
select DATEADD(month, @intFlag, GETDATE())  
SET @intFlag = @intFlag + 1
END

In SQL Oracle, you can easily create a list of dates using CONNECT BY. For example, if you want all the months between '2000-12-31' and today:

select add_months(date '2000-12-31',level) dates
from dual 
connect by level <=  months_between(sysdate, date '2000-12-31');

The function used to obtain the number of months, here months_between , can change between different SQL versions (eg in SQL Server it should be datediff() ).

You can use a dynamic script to build a calendar set.
A good example can be found here:
http://blog.namwarrizvi.com/?p=139

In that example you would just replaced the DATEADD and DATEDIFF to use months instead of days.

There is a generic elegant solution on the problem here: Get usernames logged in on day by day basis from database

Of course, it will require adjustments, but the principle is great.

It's often useful to keep a table of incrementing values, as large as you need it to be:

create table sequence ( value int not null primary key clustered )
insert sequence values(0)
insert sequence values(1)
insert sequence values(2)
insert sequence values(3)
. . .
insert sequence values(n)

With such a table, producing a list of any size is trivial. This will give you 36 date/time values a month apart, starting with the current date/time.

select top 36
       dtValue = dateadd( month , sequence.value , date(current_timestamp) )
from dbo.sequence
order by sequence.value

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM