Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите с запросом  [new]
__Avenger__
Member

Откуда:
Сообщений: 1975
Добрый день!

Пусть есть данные:
set dateformat dmy
declare @t table (date datetime, Num int)

insert into @t values 
('01-02-2016',1),
('02-02-2016',1),
('03-02-2016',0), 
('04-02-2016',1),
('08-02-2016',1);


Необходимо в порядке возрастания дат и при изменении признака Num получить следующие интервалы:
01-02-2016 03-02-2016 1
03-02-2016 04-02-2016 0
04-02-2016 08-02-2016 1

Как такое можно сделать?

Спасибо.
4 дек 18, 17:00    [21753369]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
__Avenger__
Member

Откуда:
Сообщений: 1975
А если упростить задачу:

01-02-2016 02-02-2016 1
03-02-2016 03-02-2016 0
04-02-2016 08-02-2016 1

?
4 дек 18, 17:48    [21753480]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
waszkiewicz
Member

Откуда:
Сообщений: 925
__Avenger__,

если версия сервера позволяет - lead
4 дек 18, 17:51    [21753484]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
invm
Member

Откуда: Москва
Сообщений: 8203
select
 min(t.date), isnull(a.date, b.date), t.num
from
 @t t outer apply
 (select top (1) date from @t where Num <> t.Num and date > t.date order by date) a cross apply
 (select top (1) date from @t order by date desc) b
group by
 t.num, isnull(a.date, b.date)
order by
 min(t.date);
4 дек 18, 17:53    [21753489]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
court
Member

Откуда:
Сообщений: 1521
;with cte as (
	select 
		* 
		,rn	=row_number()over(order by date)
		,lag	=lag(Num)over(order by date)
		,lead	=lead(Num)over(order by date)
	from @t
),
cte1 as (
	select
		*
		,flag	=case when lag <> Num or lag is null or lead is null then rn end 
	from cte )

select 
	sDate	=t1.date
	,fDate	=a.date
	,t1.Num
from cte1 t1

cross apply (select top 1 t2.date from cte1 t2 where t2.flag>t1.flag order by t2.flag) a

where t1.flag is not null
order by t1.date
4 дек 18, 18:14    [21753519]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
court
Member

Откуда:
Сообщений: 1521
второе цте, как бы и не надо ... )
;with cte as (
	select 
		* 
		,flag	=case when lag(Num)over(order by date) <> Num or lag(Num)over(order by date) is null or lead(Num)over(order by date) is null then row_number()over(order by date) end 
	from @t
)

select 
	sDate	=t1.date
	,fDate	=a.date
	,t1.Num

from cte t1

cross apply (select top 1 t2.date from cte t2 where t2.flag>t1.flag order by t2.flag) a

where t1.flag is not null
order by t1.date
4 дек 18, 18:28    [21753552]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
Щукина Анна
Member

Откуда:
Сообщений: 1137
court
второе цте, как бы и не надо ... )
+

;with cte as (
	select 
		* 
		,flag	=case when lag(Num)over(order by date) <> Num or lag(Num)over(order by date) is null or lead(Num)over(order by date) is null then row_number()over(order by date) end 
	from @t
)

select 
	sDate	=t1.date
	,fDate	=a.date
	,t1.Num

from cte t1

cross apply (select top 1 t2.date from cte t2 where t2.flag>t1.flag order by t2.flag) a

where t1.flag is not null
order by t1.date
да тут много чего, помимо СТЕ, можно выкинуть. ;)

Как вариант:
set dateformat dmy
declare @t table (date datetime, Num int)

insert into @t values 
('01-02-2016',1),
('02-02-2016',1),
('03-02-2016',0), 
('04-02-2016',1),
('08-02-2016',1);

--
--
select min(date) as date_start
     , max(date) as date_end
     , lead(min(date),1,max(date)) over(order by min(date))
     , num
  from (
         select * 
              , row_number() over(partition by num order by date)
              - row_number() over(order by date) as grp_id
           from @t
       ) v
 group by num, grp_id
 order by min(date)
5 дек 18, 06:22    [21753884]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
Щукина Анна
Member

Откуда:
Сообщений: 1137
Щукина Анна
court
второе цте, как бы и не надо ... )
+

;with cte as (
	select 
		* 
		,flag	=case when lag(Num)over(order by date) <> Num or lag(Num)over(order by date) is null or lead(Num)over(order by date) is null then row_number()over(order by date) end 
	from @t
)

select 
	sDate	=t1.date
	,fDate	=a.date
	,t1.Num

from cte t1

cross apply (select top 1 t2.date from cte t2 where t2.flag>t1.flag order by t2.flag) a

where t1.flag is not null
order by t1.date
да тут много чего, помимо СТЕ, можно выкинуть. ;)

Как вариант:
set dateformat dmy
declare @t table (date datetime, Num int)

insert into @t values 
('01-02-2016',1),
('02-02-2016',1),
('03-02-2016',0), 
('04-02-2016',1),
('08-02-2016',1);

--
--
select min(date) as date_start
     , max(date) as date_end -- "А если упростить задачу:"(с)
     , lead(min(date),1,max(date)) over(order by min(date)) as date_end_1 -- Исходная постановка задачи
     , num
  from (
         select * 
              , row_number() over(partition by num order by date)
              - row_number() over(order by date) as grp_id
           from @t
       ) v
 group by num, grp_id
 order by min(date)

:)
5 дек 18, 06:26    [21753885]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с запросом  [new]
__Avenger__
Member

Откуда:
Сообщений: 1975
Спасибо.
7 дек 18, 00:47    [21756515]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить