2016-09-06 111 views
0

我需要獲取包括當前月份在內的所有前幾個月的最後一天,直到指定月份。例如,我需要九月的最後幾天,八月,七月,六月,可四月,三月,二月,一月,2015年12月,像這樣:TSQL從前幾個月的最後一天到指定月份

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月等。有沒有辦法讓我可以做一個循環,並做到這一點,而不必分別計算每個月末?

回答

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 
+0

你的答案是第一個,它的工作原理,但是我對上述如何成爲「遞歸」有點困惑?換句話說,實際的'循環/遞歸'如何/在哪裏發生? –

+0

CTE定義中查詢的第二部分是遞歸發生的地方。 CTE中從CTE中選擇的部分:) –

+0

謝謝你的解釋傑夫! –

1

以下是一種方法,使用CTE生成遞增數字列表,以便我們可以選擇某些內容並在DATEADD中使用以返回適當的月數。

通常,如果你這樣做的頻率很高,而不是像CROSS JOIN一樣快速生成數字,我建議只創建一個「數字」表,它只保存1到「數字」足夠高以滿足您的需求「

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 
3

with temp as (select -1 i union all select i+1 i from temp where i < 8) select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+i*-1,0)) from temp

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 
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 
+0

我需要它返回而不是轉發,但如果將來出現問題,則可能會提供幫助。 +1。 –

0

的版本里,很快那兒剽竊在一起,根據不同的一對夫婦的部分,這樣的答案:

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); 
相關問題