TSQL获得前几个月的最后一天达到指定月份

时间:2016-09-06 15:15:25

标签: sql-server tsql

我需要获得前几个月的最后一天,包括当月,直到指定月份。例如,我需要9月,8月,7月,6月,5月,3月,3月,2015年1月,2015年12月的最后几天:

temptable_mytable

last_day_of_month
-----------------
2016-09-30
2016-08-31
2016-07-31
2016-06-30
2016-05-31
2016-04-30
2016-03-31
2016-02-30
2016-01-31
2015-12-31

我需要指定要回溯的月份和年份 - 在上述情况下是2015年12月,但也可能是2015年9月等。有没有办法让我可以做一个循环而不必每个月结束时单独计算?

6 个答案:

答案 0 :(得分:3)

使用带有EOMONTH功能的递归CTE。

DECLARE @startdate DATE = '2016-01-01'

;WITH CTE
AS
(
    SELECT EOMONTH(GETDATE()) as 'Dates'
    UNION ALL
    SELECT EOMONTH(DATEADD(MONTH, -1, [Dates]))
    FROM CTE WHERE Dates > DATEADD(MONTH, 1, @startdate)
)

SELECT * FROM CTE

答案 1 :(得分:3)

display: inline-block;

答案 2 :(得分:2)

declare @LASTMONTH date = '2018-10-01';


WITH MTHS AS (
                SELECT dateadd(month,month(getdate()),dateadd(year,year(getdate()) - 1900, 0)) aday
                UNION ALL
                SELECT DATEADD(month,1,aday) from MTHS WHERE  aday <= @LASTMONTH
                ),
    LASTDAYS AS (SELECT DATEADD(day,-1,aday) finaldayofmonth from MTHS)     
select * from LASTDAYS 

这是一个适当前进或后退的版本

declare @LASTMONTH date = '2013-10-01';


WITH DIF AS (SELECT CASE WHEN 
                        YEAR(@LASTMONTH) * 12 + MONTH(@LASTMONTH) 
                        >= YEAR(GETDATE()) * 12 + MONTH(getdate()) THEN 1 ELSE -1 END x),
MTHS AS (
                SELECT dateadd(month,month(getdate()),dateadd(year,year(getdate()) - 1900, 0)) aday 
                UNION ALL
                SELECT DATEADD(month,(SELECT X from dif),aday) from MTHS 
                        WHERE  month(aday)  !=  month(dateadd(month,1,@LASTMONTH)) or YEAR(aday) != YEAR(dateadd(month,1,@LASTMONTH))
                ),
    LASTDAYS AS (SELECT DATEADD(day,-1,aday) finaldayofmonth from MTHS)     
select * from LASTDAYS order by finaldayofmonth 

答案 3 :(得分:1)

这是一种方法,使用CTE生成递增数字列表,以便我们可以选择并在DATEADD中使用以返回适当的月数。

通常情况下,如果您经常这样做,而不是像CROSS JOIN那样动态生成数字,我建议只创建一个&#34;数字&#34;只保存从1到#34的数字的表格;某些数字足以满足您的需求&#34;

DECLARE @Date DATE = '20151201'
DECLARE @MonthsBackToGo INTEGER
SELECT @MonthsBackToGo = DATEDIFF(mm, @Date, GETDATE()) + 1;

WITH _Numbers AS
(
SELECT TOP (@MonthsBackToGo) ROW_NUMBER() OVER (ORDER BY o.object_id) AS Number
    FROM sys.objects o
        CROSS JOIN sys.objects  o2
)

SELECT  EOMONTH(DATEADD(mm, -(Number- 1), GETDATE())) AS last_day_of_month
FROM _Numbers

答案 4 :(得分:1)

无论你为原始桌子或物体返回或前进多远,都应该向外扩展。

SET NOCOUNT ON;

DECLARE @Dates TABLE ( dt DATE)

DECLARE @Start DATE = DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), 0)
DECLARE @End DATE = DATEADD(YEAR, 1, @Start)

WHILE @Start <= @End
BEGIN
    INSERT INTO @Dates (dt) VALUES (@Start)

        SELECT @Start = DATEADD(DAY, 1, @Start)
END


; With x as 
    (
    Select 
        dt
    ,   ROW_NUMBER() OVER(PARTITION BY DATEPART(YEAR, Dt), DATEPART(MONTH, Dt) ORDER BY Dt Desc) AS rwn
 From @Dates
)
Select *
From x
WHERE rwn = 1
ORDER BY Dt

答案 5 :(得分:0)

基于这些部分的几个不同的SO答案,这是快速拼凑在一起的:

DECLARE @startdate datetime, @enddate datetime

set @startdate = '2015-12-01'
set @enddate = getdate()

;WITH T(date)
AS
( 
SELECT @startdate
UNION ALL
SELECT DateAdd(day,1,T.date) FROM T WHERE T.date < @enddate
)
SELECT DISTINCT
DATEADD(
    day, 
    -1,
    CAST(CAST(YEAR(date) AS varchar) + '-' + CAST(MONTH(date)AS varchar) + '-01' AS DATETIME))
FROM T OPTION (MAXRECURSION 32767);