CREATE TABLE [tmp].[forFindDate]( [date] [datetime] NOT NULL, [value] [int] NOT NULL, CONSTRAINT [PK_forFindDate] PRIMARY KEY CLUSTERED ( [date] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170401', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170402', 20) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170403', 20) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170404', 20) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170405', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170406', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170407', 30) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170408', 36) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170409', 35) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170410', 30) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170411', 30) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170412', 20) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170413', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170414', 40) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170415', 40) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170416', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170417', 50) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170418', 52) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170419', 53) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170420', 53) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170421', 50) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170422', 51) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170423', 52) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170424', 50) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170425', 50) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170426', 50) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170427', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170428', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170429', 10) INSERT INTO [tmp].[forFindDate] ([date], [value]) VALUES ('20170430', 10) GO
declare @planValue int = 15 -- left select top 1 ' ', BeginDate, DATEADD(Day, -1, EndDate) EndDate from (select s.date BeginDate, ISNULL(min(e.date), '20170501') EndDate from [tmp].[forFindDate] s left join [tmp].[forFindDate] e on s.date < e.date and not e.value > @planValue where s.value > @planValue group by s.date) tmp order by DATEDIFF(day, BeginDate, EndDate) desc -- with ;with periodDate1 as( select s.date BeginDate, ISNULL(min(e.date), '20170501') EndDate from [tmp].[forFindDate] s left join [tmp].[forFindDate] e on s.date < e.date and not e.value > @planValue where s.value > @planValue group by s.date ) select top 1 ' (with left)' title, BeginDate, DATEADD(Day, -1, EndDate) EndDate from periodDate1 order by DATEDIFF(day, BeginDate, EndDate) desc -- full ;with periodDate2 as( select s.date BeginDate, ISNULL(min(e.date), '20170501') EndDate from [tmp].[forFindDate] s full join [tmp].[forFindDate] e on s.date < e.date and not e.value > @planValue where s.value > @planValue group by s.date ) select top 1 ' (with full)' title, BeginDate, DATEADD(Day, -1, EndDate) EndDate from periodDate2 order by DATEDIFF(day, BeginDate, EndDate) desc -- right ;with periodDate3 as( select ISNULL(max(s.date), '20170401') BeginDate, e.date EndDate from [tmp].[forFindDate] s right join [tmp].[forFindDate] e on s.date < e.date and not s.value > @planValue where e.value > @planValue group by e.date ) select top 1 ' (with right)' title, DATEADD(Day, 1, BeginDate) BeginDate, EndDate from periodDate3 order by DATEDIFF(day, BeginDate, EndDate) desc
declare @planValue int = 15 ;with periodDate4 as( select s.date BeginDate, ISNULL((select DATEADD(DAY, -1, isNull(min(d.date), '20170501')) from [tmp].[forFindDate] d where d.date > s.date and not d.value > @planValue), '20170501') EndDate from [tmp].[forFindDate] s where s.value > @planValue ) select top 1 ' ', p.BeginDate, p.EndDate from periodDate4 p order by DATEDIFF(DAY, p.BeginDate, p.EndDate) desc
declare @planValue int = 15 ;with periodDate5 as( select s.date BeginDate, ISNULL(min(e.date), '20170501') EndDate from [tmp].[forFindDate] s outer apply ( -- ( ) select top 1 ee.date from [tmp].[forFindDate] ee where s.date < ee.date and not ee.value > @planValue ) e where s.value > @planValue group by s.date ) select top 1 'sql 2005 apply' title, BeginDate, DATEADD(Day, -1, EndDate) EndDate from periodDate5 order by DATEDIFF(day, BeginDate, EndDate) desc
declare @planValue int = 15 ;with periodDate6 as ( select f.date BeginDate, DATEADD(day, 1, f.date) EndDate from [tmp].[forFindDate] f where f.date = '20170417' and f.value > @planValue union all select r.BeginDate, DATEADD(day, 1, f.date) EndDate from [tmp].[forFindDate] f inner join periodDate6 r on r.EndDate = f.Date and value > @planValue ) select top 1 'recursive' title, BeginDate, DATEADD(Day, -1, EndDate) EndDate from periodDate6 order by DATEDIFF(day, BeginDate, EndDate) desc
OVER ( PARTITION BY iif(f.value < @planValue, 1, 0) order by f.date)
declare @planValue int = 15 with tmp as ( select '20170331' [date] union all select date from [tmp].[forFindDate] f where f.value < @planValue union all select '20170501' ), periodDate4 as ( select date beforDate, lead(f.date, 1, '20170501') OVER (order by f.date) afterDate from tmp f ) select top 1 'func 2012 t' title, DATEADD(Day, 1, beforDate) BeginDate, DATEADD(Day, -1, afterDate) EndDate from periodDate4 order by DATEDIFF(day, beforDate, afterDate) desc
declare @planValue int = 15 ;with periodDate8 as( select ISNULL(s.date, '20170401') BeginDate, ISNULL(e.date, '20170501') EndDate from [tmp].[forFindDate] s, [tmp].[forFindDate] e ) select top 1 'for Fun', p.BeginDate, p.EndDate from periodDate8 p left join [tmp].[forFindDate] b on b.date between p.BeginDate and p.EndDate and not b.value > @planValue where p.BeginDate < p.EndDate and b.date is null order by DATEDIFF(day, BeginDate, EndDate) desc
declare @planValue int = 15 declare @endDate datetime = null, @Intervat int = 0, @maxIntervat int = 0, @old_date datetime = '20170401', @cur_date datetime DECLARE date_cursor CURSOR FOR SELECT date FROM [tmp].[forFindDate] where value > @planValue OPEN date_cursor FETCH NEXT FROM date_cursor INTO @cur_date WHILE @@FETCH_STATUS = 0 BEGIN IF (@cur_date = DATEADD(DAY, 1, @old_date)) BEGIN SET @Intervat = @Intervat + 1 IF(@Intervat > @maxIntervat) BEGIN SET @maxIntervat = @Intervat SET @endDate = @cur_date END END else Begin set @Intervat = 0 end SET @old_date = @cur_date FETCH NEXT FROM date_cursor INTO @cur_date END CLOSE date_cursor; DEALLOCATE date_cursor; select 'cursor' title, DATEADD(DAY, - @maxIntervat, @endDate) BeginDate, @endDate EndDate
declare @planValue int = 15 ;WITH Step01 AS (SELECT * FROM tmp.forFindDate WHERE value > @planValue ) , Step02 AS (SELECT date , CASE WHEN date - LAG([date], 1, '20170401') OVER(ORDER BY date) > 1 THEN 1 ELSE 0 END AS isStart , CASE WHEN LEAD([date], 1, '20170430') OVER(ORDER BY date) - date > 1 THEN 1 ELSE 0 END AS isEnd FROM Step01) , Step03 AS ( SELECT date AS rangestart , CASE WHEN isEnd = 1 THEN date ELSE LEAD(date, 1) OVER(ORDER BY date) END AS rangeend , isstart FROM Step02 WHERE isstart = 1 OR isend = 1) SELECT TOP 1 rangestart , rangeend , DATEDIFF(day, rangestart, rangeend) AS '' FROM Step03 WHERE isstart = 1 ORDER BY '' DESC
declare @planValue int = 15 ;with internals AS ( SELECT dateadd(day, -ROW_NUMBER() OVER (ORDER BY date), [date]) fake_start, [date] FROM tmp.forFindDate where value > 15 ) SELECT TOP 1 'new method' as title, MIN([date]) AS BeginDate, MAX([date]) AS EndDate FROM internals GROUP BY fake_start ORDER BY COUNT(*) DESC
Source: https://habr.com/ru/post/327862/
All Articles