这类似于mySQL问题,除了我只想要月末日期:Get a list of dates between two dates
我希望能够输入两个日期,例如:
SELECT EndOfMonth('1/1/2015', '1/1/2017');
返回的结果应该是
EndOfMonth
1/31/2015
2/28/2015
3/31/2015
.
.
.
10/31/2016
11/30/2016
12/31/2016
我使用的SQL Server版本是2008,所以我实际上无法访问EOMONTH()。
答案 0 :(得分:3)
使用数字表可以让事情变得更轻松。如果您还没有数字表,可以使用以下sql创建一个(取自this SO post):
SELECT TOP 10000 IDENTITY(int,0,1) AS Number
INTO Tally
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Tally ADD CONSTRAINT PK_Tally PRIMARY KEY CLUSTERED (Number)
要详细了解数字表及其使用方法,请阅读Jeff Moden的The "Numbers" or "Tally" Table: What it is and how it replaces a loop文章。
使用EOMONTH
内置功能后,使用数字表对2012或更高版本来说相当容易:
DECLARE @Start date = '2015-01-01', @End date = '2017-01-01'
SELECT EOMONTH(DATEADD(MONTH, Number, @Start))
FROM Tally
WHERE Number < DATEDIFF(MONTH, @Start, @End)
对于早期版本,您可以使用DATEADD
和DATEDIFF
来获取上个月的最后一天,然后只需添加一个月:
SELECT DATEADD(DAY, -DATEPART(DAY, @Start), (DATEADD(MONTH, Number+1, @Start)))
FROM Tally
WHERE Number < DATEDIFF(MONTH, @Start, @End)
答案 1 :(得分:2)
您可以使用Common Table表达式(CTE)轻松实现此目的。
--Declaration of start date and end date
declare @StartDate datetime='2017-01-01', @endDate datetime='2017-12-01'
-- Expression
;WITH monthcte
AS (SELECT EOMONTH(@StartDate) AS dates
UNION ALL
SELECT DATEADD(month, 1, dates) AS dates
FROM monthcte
WHERE dates <@endDate
)
-- Select query over expression
SELECT EOMONTH(dates) AS EndOfMonth
FROM monthcte
Order by EndOfMonth
答案 2 :(得分:0)
如果您无法使用EOMonth,可以按如下方式生成:
declare @d1 date = '1/1/2015'
declare @d2 date = '1/1/2017'
select top (datediff(MONTH,@d1,@d2)+1) Dates = DateAdd(day,-1, Dateadd(M,Row_number() over(order by (select null)), @d1)) from
master..spt_values n1, master..spt_values n2
如果您的SQL Server版本中有EoMonth,那么您可以尝试如下:
select top (datediff(MONTH,@d1,@d2)+1) Dates = EoMonth(Dateadd(M,Row_number() over(order by (select null))-1, @d1)) from
master..spt_values n1, master..spt_values n2
答案 3 :(得分:0)
月份列表:
DECLARE @StartDate datetime
DECLARE @EndDate datetime
set @StartDate = '01/01/2015'
set @EndDate = '01/01/2017'
;WITH cte1 (S) AS (
SELECT 1 FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (S)
),
cte2 (S) AS (SELECT 1 FROM cte1 AS cte1 CROSS JOIN cte1 AS cte2),
cte3 (S) AS (SELECT 1 FROM cte1 AS cte1 CROSS JOIN cte2 AS cte2)
select distinct cast(result as date) result from
(SELECT TOP (DATEDIFF(day, @StartDate, @EndDate) + 1)
result = DATEADD(day, ROW_NUMBER() OVER(ORDER BY S) - 1, @StartDate)
FROM cte3) as res