【问题标题】:SQL function for last 12 months过去 12 个月的 SQL 函数
【发布时间】:2013-12-10 11:17:24
【问题描述】:

我正在寻找一个 SQL 函数,它提供过去 12 个月的开始日期和结束日期。假设您选择 10.Dec,它将给出结果:

 - StartDate   --   EndDate 
 - 2013-11-01  -  2013-11-30
 - 2013-10-01  -  2013-10-31
 - 2013-09-01  -  2013-09-30 

过去 12 个月也是如此。

我尝试修改我们拥有的旧功能,但最终我完全脱离并感到困惑。

ALTER FUNCTION [dbo].[Last12Months](@Date date) RETURNS TABLE 
AS  
Return
( 
with cte as (
SELECT DATEADD(mm, DATEDIFF(mm, 01, @Date), 01) AS Start,
       DATEADD(mm, DATEDIFF(mm, -12, @Date), -12) AS EndDate
 union all
select Start - 1, EndDate - 1 from cte
where Start >= @Date )
select CAST(Start as DATE) StartDate, CAST(EndDate as DATE) EndDate from cte)

像这样运行它:

select * from dbo.Last12Months ('2013-12-10')

得到:

 - StartDate   -  EndDate 
 - 2013-12-02  -  2013-12-20

有人知道该怎么做吗?

【问题讨论】:

标签: sql sql-server function date


【解决方案1】:

请尝试使用 CTE:

ALTER FUNCTION [dbo].[Last12Months]
(
    @Date datetime
)   RETURNS @tbl TABLE (Start datetime, EndDate datetime)
AS   
BEGIN
    WITH T AS(
    SELECT 
        DATEADD(month, DATEDIFF(month, 0, @Date), 0) AS Start,
        DATEADD(d, -DAY(DATEADD(m,1,@date)),DATEADD(m,1,@date)) AS EndDate,
        12 Cnt
    UNION ALL
    SELECT 
        DATEADD(month, -1, Start),
        DATEADD(d, -DAY(DATEADD(m,1,Start-1)),DATEADD(m,1,Start-1)),
        Cnt-1
    FROM
        T
    WHERE
        Cnt-1>0
    )
    INSERT INTO @tbl 
        (Start, EndDate)
    SELECT 
        Start, EndDate
    FROM T

    RETURN
END

【讨论】:

  • 问题是,一旦 CTE 到达 2 月,结束日期就会被限制为 28 日或 29 日,并且从该值计算出的每个后续结束日期同样将是 28 日或 29 日,而不是 30 日或 31 日。
  • 是的。这是非常真实的。月份必须是全天:) 无论如何谢谢!
  • 呃,你为什么要把日期转换成NVARCHAR
  • 我无法运行此程序,消息 156,级别 15,状态 1,过程 Last12Months,第 2 行关键字“声明”附近的语法不正确。消息 102,级别 15,状态 1,过程 Last12Months,第 13 行 ',' 附近的语法不正确。我在开头添加了 ALTER 函数 [dbo].[Last12Months]。先生,我做错了什么?
  • 完美!你是我的救星。非常感谢:)
【解决方案2】:

这似乎可以完成这项工作 - 无论您是想将它放在一个函数中还是只是放在任何需要数据的地方:

; With Numbers as (
    select ROW_NUMBER() OVER (ORDER BY number ) as n
    from master..spt_values
), Months as (
    select DATEADD(month,n,'20010101') as start_date,
           DATEADD(month,n,'20010131') as end_date
    from Numbers
)
select * from Months
where DATEDIFF(month,start_date,GETDATE()) between 0 and 11

(如果您想根据其他日期获取GETDATE(),请替换任何其他日期)

(在我的机器上,这可以生成从 2001 年 1 月到至少下个世纪的任何月份 - 如果您还需要更早或更晚的日期,可以对其进行调整)

【讨论】:

  • 我需要从我在日历中选择的日期开始的 12 个之前的日期。因此,如果我选择今天,我将获得 12 月之前所有月份的开始日期和结束日期。
  • @user3086563 - 正如我在下面所说,只需在最后一行将您想要工作的日期替换为 GETDATE(),它将生成前 11 个月(加上提供日期的月份在)。如果需要在当前月份之前 12 个月,只需将between 更改为between 1 and 12
【解决方案3】:

该死的,你必须快点!

很好地使用 CTE:我已经学会了回答这个问题...

alter function Last12Months(@d date) returns table
as
return(
with cte as (
    select 
        dateadd(month, datepart(mm,@d)-13, 
            dateadd(year,datepart(yyyy,@d)-1900,0)
            )
        as start
    union all
      select dateadd(mm, 1, start) from cte
      where start < @d)
select start, dateadd(mm, 1, start) ends from cte
    where start < @d
)
go

select * from  Last12Months('2014-06-04')

删除了到 varchar 的转换,这要归功于 Date serial in SQL?

这将返回 13 个月:从去年六月到今年六月,包括在内。

要返回前 12 个月,不包括当前 6 月,请将最终开始时间

where start < dateadd(month, datepart(mm,@d)-1, 
    dateadd(year,datepart(yyyy,@d)-1900,0))

下个月第一天 00:00 时结束。

【讨论】:

  • 这似乎可以完成这项工作:) 是否有可能减少 1 天?所以我们只能得到准确的月份。
  • 怎么样!您是否想要最多 12 个月但不包括当月?
  • 是的,这就是我想要的。因此,如果我选择今天的日期,我会得到 Nov2012-Nov2013 而且我还想要从 1 日到月底,而不是从 1 日到 1 日,如果你让我兄弟的话。无论如何,谢谢,这对我帮助很大。
  • select start, dateadd(second,-1,dateadd(month, 1, start)) ends from cte where start &lt; @d 在每月最后一天 23:59:59 为您提供服务
【解决方案4】:

检查一下,

Declare @i date='2013-12-10'

;with cte as

(Select dateadd(month,datediff(month,0,@i)-1,0) StartDate
,dateadd(day,-1,dateadd(month,datediff(month,0,@i),0)) EndDate ,1 rownum

Union all

select dateadd(month,-1,StartDate),dateadd(day,-1,StartDate),rownum+1 rownum from cte where rownum<12 )

select * from cte

【讨论】:

    【解决方案5】:

    试试这个可能对你有帮助

    select top 12 *
    from YourTable
    where dateOf between @DateFrom and @DateTo
    order by dateOf  desc
    

    【讨论】:

    • 我没有可供选择的表格。我想制作一个在我的日历中使用的函数,它给出了最后一个月的 12 个月。这几个月我将进一步使用来获取销售信息。
    【解决方案6】:

    @Lebowski 下面的脚本将按时间顺序为您提供从今天起指定日历月的开始和结束日期

    DECLARE @nMonths TINYINT 
    SET @nMonths = 60
    SELECT FORMAT(DATEADD(month, n.n - @nMonths+1+ DATEDIFF(month, 0, GETDATE()) -1 ,0), 'yyyy-MM-dd')               AS MonthStartDate
    ,      FORMAT(DATEADD(dd, -1, DATEADD(month, n.n - @nMonths+1 + DATEDIFF(month, 0, GETDATE()),0)), 'yyyy-MM-dd') AS MonthEndDate
    FROM (SELECT TOP(@nMonths) n = ROW_NUMBER() OVER (ORDER BY NAME)
    FROM master.dbo.syscolumns) n
    

    样本输出

    MonthStartDate  MonthEndDate
    2011-04-01  2011-04-30
    2011-05-01  2011-05-31
    2011-06-01  2011-06-30
    2011-07-01  2011-07-31
    2011-08-01  2011-08-31
    2011-09-01  2011-09-30
    2011-10-01  2011-10-31
    2011-11-01  2011-11-30
    2011-12-01  2011-12-31
    ....
    

    【讨论】:

    • SELECT n , FORMAT(DATEADD(month, DATEDIFF(month, 0, GETDATE()) - Series.n + 1,0), 'yyyy-MM-dd') AS MonthStartDate , FORMAT( DATEADD(dd, -1, DATEADD(month, DATEDIFF(month, 0, GETDATE()) - Series.n + 2,0)), 'yyyy-MM-dd') AS MonthEndDate FROM (SELECT TOP 50 ROW_NUMBER() OVER (ORDER BY NAME) AS n FROM master.dbo.syscolumns) AS 系列
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 2018-08-29
    • 2021-02-11
    相关资源
    最近更新 更多