【问题标题】:Create list of dates, a month apart, starting from current date从当前日期开始创建日期列表,相隔一个月
【发布时间】:2011-07-05 20:53:34
【问题描述】:

我正在寻找一个简单的选择查询(不使用表格)来返回一个日期列表,相隔 1 个月。输出应该看起来像这样,(假设 GetDate() = '2011-07-05 11:59:000' 我想要介于 NOW() 和 NOW()+4 个月之间

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

让我头疼的部分是计算明年,例如,如果我在 11 月运行此查询,月份应列为 11、12、1、2。谢谢!

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    如果要求不固定,您可以使用递归 CTE,并且不需要将 UNION 串在一起:

     ;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) 

    当谈到性能并且你只需要 4 个月以上时,UNION 远远优于递归选项。

    【讨论】:

    • 您的脚本很好,我有点担心,因为您更改了 maxrecursion。它或多或少是一样的。所以我删除了我的并给了你信用。在这种情况下,您不需要“order by”。
    • 我不确定当我在某处读到时使用递归来确保排序,但是感谢您的澄清!
    【解决方案2】:

    @JNK 的回答,刚刚重做给你连续的每个日期:

    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'
    

    今天早上不得不做这样的事情!

    【讨论】:

    • 问题是:除了一堆UNIONs之外,你知道更短的方法吗?
    • 完美的瑞恩,谢谢!一个简短的方法会很好,但这有效。谢谢!
    • @Russ 您也可以为此使用递归 CTE。
    【解决方案3】:

    我更喜欢通过循环数据并根据当前(或目标)日期构建列表来处理这些小(一次性)情况:

    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
    

    【讨论】:

      【解决方案4】:
      SELECT GETDATE(),
             DATEADD(month, 1, GETDATE()),    
             DATEADD(month, 2, GETDATE()),
             DATEADD(month, 3, GETDATE()),
             DATEADD(month, 4, GETDATE())
      

      DATEADD 为您处理所有年份考虑逻辑,以及闰年等。

      显然这会返回一个列列表。请参阅 Ryan 对行解决方案的回答!

      【讨论】:

      • +1 但如果您想要更多的日期,很快就会变得笨拙。
      【解决方案5】:

      试试这个:

      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
      

      【讨论】:

        【解决方案6】:

        您可以使用动态脚本来构建日历集。
        一个很好的例子可以在这里找到:
        http://blog.namwarrizvi.com/?p=139

        在该示例中,您只需替换 DATEADDDATEDIFF 以使用月而不是天。

        【讨论】:

        • 请注意OP的第一句话:我正在寻找一个简单的选择查询(不使用表格)
        • 请注意,这不会INSERT 进入任何内容,“日历表”只是他所追求的常用措辞。我将编辑我的答案说“日历集”,因为没有相应的INSERT,这正是它的含义。
        【解决方案7】:

        这里有一个通用的优雅解决方案:Get usernames logged in on day by day basis from database

        当然是需要调整的,但是原理很好。

        【讨论】:

          【解决方案8】:

          在 SQL Oracle 中,您可以使用 CONNECT BY 轻松创建日期列表。 例如,如果您想要 '2000-12-31' 和今天之间的所有月份:

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

          用于获取月数的函数,这里months_between,可以在不同的SQL版本之间改变(例如在SQL Server中应该是datediff())。

          【讨论】:

            【解决方案9】:

            保留一个递增值表通常很有用,只要你需要它就可以:

            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)
            

            有了这样的表,生成任何大小的列表都是微不足道的。这将为您提供每个月相隔 36 个日期/时间值,从当前日期/时间开始。

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-08-22
              • 2012-10-27
              • 2018-10-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-07-17
              相关资源
              最近更新 更多