tsql:如何检索给定日期范围之间每个月的最后日期

时间:2013-09-18 09:59:35

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

我有两个日期,例如08/08/2013和11/11/2013,我需要从8月到11月的每个月的最后一个日期在一个表中,以便我可以遍历表格来单独选择这些日期。

我知道如何选择任何一个月的最后日期,但我被一个日期范围所困扰。

友好的帮助,我们将非常感激。

注意:我使用的是Sql 2008,日期范围可能是1个月,2个月或6个月或一年或者最大值。

9 个答案:

答案 0 :(得分:7)

您可以使用CTE获取定义范围内该月的所有最后几天

Declare @Start datetime
Declare @End datetime

Select @Start = '20130808'
Select @End = '20131111'
;With CTE as
(
Select @Start  as Date,Case When DatePart(mm,@Start)<>DatePart(mm,@Start+1) then 1 else 0 end as [Last]
UNION ALL
Select Date+1,Case When DatePart(mm,Date+1)<>DatePart(mm,Date+2) then 1 else 0 end from CTE
Where Date<@End
)

Select * from CTE
where [Last]=1   OPTION ( MAXRECURSION 0 )

答案 1 :(得分:2)

我创建了一个表变量,用@startDate@endDate之间的所有日期填充它,并搜索了该月的最大日期。

declare @tmpTable table (dates date)
declare @startDate date = '08/08/2013'
declare @endDate date = '11/11/2013'

while @startDate <= @endDate
begin
    insert into @tmpTable (dates) values (@startDate)
    set @startDate = DATEADD(DAY, 1, @startDate)
end

select max(dates) as [Last day] from @tmpTable as o
group by datepart(YEAR, dates), datepart(MONTH, dates)

结果:

Last day
2013-08-31
2013-09-30
2013-10-31
2013-11-11

也要在11月的最后一天,这可以在循环之前使用:

set @endDate = DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, @endDate) + 1, 0))

答案 2 :(得分:2)

DECLARE @tmpTable table (LastDates DATE);
DECLARE @startDate DATE = '01/01/2012'; --1 Jan 2012
DECLARE @endDate DATE = '05/31/2012';   --31 May 2012
DECLARE @tmpEndDate DATE;

SET @startDate = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@startDate)+1,1));
SET @tmpEndDate = DATEADD(DAY, 1, @endDate);

WHILE (@startDate <= @tmpEndDate)
BEGIN   
    INSERT INTO @tmpTable (LastDates) values (DATEADD(DAY, -1, @startDate));
    SET @startDate = DATEADD(MONTH, 1, @startDate);
END

SELECT [LastDates] FROM @tmpTable;

<强>输出:

示例:1

@startDate DATE = '01/01/2012'; --1 Jan 2012
@endDate DATE = '05/31/2012';   --31 May 2012

LastDates
----------
2012-01-31
2012-02-29
2012-03-31
2012-04-30
2012-05-31

示例:2

@startDate DATE = '11/01/2011'; --1 Nov 2011
@endDate DATE = '03/13/2012';   --13 Mar 2012

LastDates
----------
2011-11-30
2011-12-31
2012-01-31
2012-02-29

答案 3 :(得分:1)

以下脚本演示了用于查找上一个,当前和下个月的最后一天的脚本。

----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth

如果您想查找任何指定日期的最后一天,请使用以下脚本。

--Last Day of Any Month and Year
DECLARE @dtDate DATETIME
SET @dtDate = '8/18/2007'
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@dtDate)+1,0))
LastDay_AnyMonth
ResultSet:
LastDay_AnyMonth

源 - SQL Server Central。

答案 4 :(得分:1)

您可以使用递归CTE执行此操作,请注意MAXRECURSION OPTION可以阻止无限循环:

DECLARE @StartDate DATE = '2013-08-08'
DECLARE @EndDate DATE = '2013-11-11'

;WITH dateCTE
AS
(
    SELECT CAST(DATEADD(M, 1,DATEADD(d, DAY(@StartDate) * -1, @StartDate)) AS DATE) EndOFMonth
    UNION ALL 
    SELECT CAST(DATEADD(M, 2,DATEADD(d, DAY(EndOFMonth) * -1, EndOFMonth)) AS DATE) 
    FROM dateCTE
    WHERE EndOFMonth < DATEADD(d, DAY(@EndDate) * -1, @EndDate)

)
SELECT *
FROM dateCTE
OPTION (MAXRECURSION 30);

返回

EndOFMonth
----------
2013-08-31
2013-09-30
2013-10-31

答案 5 :(得分:0)

试试这个 最后一行(where)是日期过滤的可选项

declare @table table  
(  
thisdate date  
)


insert into @table values ('12/01/2013'),('05/06/2013'),('04/29/2013'),('02/20/2013')
select *,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,thisdate)+1,0))
LastDay from @table
where thisdate between 'givendate' and 'givendate'

以下示例适用于所有日期

thisdate    lastday
2013-12-01  2013-12-31 23:59:59.000
2013-05-06  2013-05-31 23:59:59.000
2013-04-29  2013-04-30 23:59:59.000
2013-02-20  2013-02-28 23:59:59.000

答案 6 :(得分:0)

以下CTE为您提供从1900年2月到26世纪中期(在我的机器上)的每个月的最后一天:

;with LastDaysOfMonths as (
    select DATEADD(month,
                 ROW_NUMBER() OVER (ORDER BY so.object_id),
                 '19000131') as Dt
    from sys.objects so,sys.objects so1
)
select * from LastDaysOfMonths

将它用作较大查询的一部分或将其过滤到您想要的日期应该很容易。您可以根据需要通过更改常量19000131来调整年份范围。唯一重要的事情是确保你使用了31天的月份,并且总是在第31天使用常数。

答案 7 :(得分:0)

不需要使用公共表表达式或类似的东西 - 这个简单的查询将执行此操作:

SELECT  DATEADD(d, -1, DATEADD(mm, DATEDIFF(m, 0, DATEADD(m, number, '2013-08-08')) + 1, 0)) AS EndOfMonth
FROM    master.dbo.spt_values
WHERE   'P' = type
        AND DATEADD(m, number, '2013-08-08') < '2013-11-11';

答案 8 :(得分:0)

尽管问题是@bummi已经回答的最后一天。

但这是第一次约会的解决方案,可能对某人有帮助。

获取@FromDate@ToDate之间所有月份的开始日期。

DECLARE @FromDate DATETIME = '2019-08-13'
DECLARE @ToDate DATETIME = '2019-11-25'

;WITH CTE
AS 
(
    SELECT DATEADD(DAY, -(DAY(@FromDate) - 1), @FromDate) AS FirstDateOfMonth

    UNION ALL

    SELECT DATEADD(MONTH, 1, FirstDateOfMonth)
    FROM CTE
    WHERE FirstDateOfMonth < DATEADD(DAY, -(DAY(@ToDate) - 1), @ToDate)
)
SELECT * FROM CTE

这是结果

--Result
2019-08-01 00:00:00.000
2019-09-01 00:00:00.000
2019-10-01 00:00:00.000
2019-11-01 00:00:00.000