获取每月的最后一天(SQL Server 2008R2)

时间:2018-01-11 09:34:34

标签: sql sql-server sql-server-2008

我有以下情况。我需要2013年至今的任何一个月的最后几天。

如何组合这两个sql语句?

SELECT DATEADD(m, 0, GETDATE()) --today

SELECT DATEDIFF(m, '2013-01-01', GETDATE()) --60 months for 5 years

我需要这个结果:

LastDayOfMth
=======================
2013-01-31 00:00:00.000
2013-02-28 00:00:00.000
2013-03-31 00:00:00.000
2013-04-30 00:00:00.000
2013-05-31 00:00:00.000
....
2017-12-31 00:00:00.000

7 个答案:

答案 0 :(得分:1)

使用递归CTE

DECLARE @Strt DATE = '2013-01-01'
;WITH CTE
AS
(
    SELECT
        SeqNo = 1,
        MyDate = DATEADD(M,1,DATEADD(D,-1,@Strt))

    UNION ALL

    SELECT
        SeqN = SeqNo +1,
        MyDate = DATEADD(m, 1, MyDate)
        FROM CTE
            WHERE SeqNo < DATEDIFF(m, @Strt,GETDATE())

)
SELECT
    MyDate
    FROM CTE
    OPTION (maxrecursion 0)

答案 1 :(得分:1)

您也可以通过执行动态SQL查询来执行此操作。使用WHILE循环来获取从开始日期到今天的所有月份的最后日期。

<强>查询

declare @today as date = getdate();
declare @start as date = '2013-01-01';
declare @months as int;
select @months = datediff(month, @start, @today);
declare @i as int= 1;
declare @t as table([dt] date);
while(@i <= @months)
begin
    insert into @t 
    select dateadd(day, -1, (dateadd(month, @i, @start)));
    set @i += 1;
end
select * from @t;

<强> Find a demo here

答案 2 :(得分:1)

试试这个

DECLARE @StartDate DATE='2013-01-01';

WITH Tally AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Nmbr 
    FROM master..spt_values
)
SELECT DATEADD(DAY,-1,DATEADD(MONTH,Nmbr,@StartDate)) AS EndOfNextMonth
FROM Tally
WHERE DATEADD(MONTH,Nmbr,@StartDate)<GETDATE();

Tally cte将返回一个正在运行的数字列表。 master..spt_values只是一张包含大量行的表...

查询将在日期中添加一个月并将其减少一天。

答案 3 :(得分:1)

我使用数字表,但是对于这个例子,我使用CTE生成了一个。我生成一个从-58到+ 1的数字列表,我用它来将这个月数添加到当前日期。然后我拿走这个日期的天数让我到月底:

WITH Numbers
AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY a.Num) * -1 + 2 AS Num
    FROM (VALUES (1),(2),(3),(5),(4),(6),(7),(8),(9),(10)) AS a(Num)
    CROSS APPLY
        (VALUES (1),(2),(3),(5),(6),(7)) As b(Num)
),
DateMinusMonths
AS
(
    SELECT DATEADD(m, Num , CAST(getdate() AS Date)) As d
    FROM Numbers
)
SELECT DATEADD(d, day(d) * -1, d) EOM
FROM DateMinusMonths

答案 4 :(得分:1)

这是我在尝试生成日期时使用的代码类型,我已将其更改为选择您想要的第一个月的最后一天(2013年1月31日)并要求它继续添加1个月直到今天#39;日期:

SELECT
    DATEADD(MONTH, Number, '2013-01-31') AS [Date]
FROM
    master..spt_values
WHERE
    Type = 'P'
    AND DATEADD(MONTH, Number, '2013-01-31') <= GETDATE()

答案 5 :(得分:0)

以下代码对您有所帮助,

declare @sDate datetime='2013-01-01', @eDate datetime= GETDATE()
;WITH mycte
     AS (SELECT EOMONTH(@sDate) AS dt
         UNION ALL
         SELECT DATEADD(month, 1, dt) AS dt
         FROM   mycte
         WHERE  dt <@eDate      
         )

SELECT  EOMONTH(dt) AS LastDayOfMth
FROM   mycte
Order by LastDayOfMth

答案 6 :(得分:0)

这个公式有点复杂,但它避免了循环或递归的需要。

-- End of current month.
-- Replace GETDATE() with your column.
SELECT 
    CAST(DATEADD(SECOND, -1, DATEADD(MONTH, DATEDIFF(MONTH, '2000-01-01', GETDATE()) + 1, '2000-01-01')) AS DATE) AS EOMonth
;

它计算自基准日期以来经过的月数(我使用2001-01-01,但您可以使用任何月份的第一个月)。它将相同数量的月份添加回基准日期。这给了我们下个月的开始。删除一秒会使我们回到当月的末尾。最后,作为日期进行转换会删除时间元素。

或者,您可以向数据库添加calendar table(也就是日期维度)。我管理的几乎每个数据库都有一个,我每天都使用它们。这是一个非常简单的例子:

Date         StartOfMonth  EndOfMonth
2018-01-01   2018-01-01    2018-01-31
2018-01-02   2018-01-01    2018-01-31
2018-01-03   2018-01-01    2018-01-31
...          ...           ...
2018-01-31   2018-01-01    2018-01-31

从SQL Server 2012开始,您可以使用EOMonth function。我知道这不是OP的选择,但它可能对其他人有所帮助。