2013-09-18 5 views
1

У меня есть две даты, например 08/08/2013 и 11/11/2013, и мне нужна последняя дата каждого месяца, начиная с августа по ноябрь, в чтобы я мог перебирать таблицу, чтобы выбрать эти даты по отдельности.tsql: Как получить последнюю дату каждого месяца между заданным диапазоном дат

Я знаю, как выбрать последнюю дату в течение любого месяца, но я застрял с диапазоном дат.

любезно помощь, будет весьма признателен.

Примечание: Я использую SQL Server 2008 и дата звенел может быть 1 месяц, 2 месяца или 6 месяцев или год или максимум тоже ..

+0

http://blog.sqlauthority.com/2007/08/18/sql-server -find-last-day-of-any-month-current-previous-next/ – zxc

+0

только что пошло, что ... –

+0

Что случилось с использованием запроса? – zxc

ответ

5

Вы можете использовать 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

После сценария демонстрирует сценарий, чтобы найти последний день предыдущего, текущий и следующий месяц.

----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.

0

попробовать эту последнюю строку (где) не является обязательным для даты фильтрации

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 
0

Следующий CTE дает в последний день каждого месяца с февраля 1900 года до середины 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.

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 

также получить последний день ноября этого может быть использован перед петлей:

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

Вы можете использовать рекурсивные CTE, чтобы сделать это, обратите внимание на MAXRECURSIONOPTION предотвращает бесконечный цикл:

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

Очень хорошая производительность. Он будет перебирать только 1 запись в месяц. – Chirag

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'; 
Смежные вопросы