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

Откуда:
Сообщений: 5
Всем привет. Вероятно тему сформулировал плохо, но лучше не придумал...Объясню на примере.
Имеем таблицу:
   
       DTV	     TAGVAL
26.03.2015 15:57	0
26.03.2015 15:58	0
26.03.2015 15:59	1
26.03.2015 16:00	1
26.03.2015 16:02	0
26.03.2015 16:03	1
26.03.2015 16:04	1
26.03.2015 16:06	1
26.03.2015 16:07	0
26.03.2015 16:09	10
26.03.2015 16:10	10
26.03.2015 16:11	0
26.03.2015 16:12	0


Нужно исключить повторяющиеся значения TAGVAL, но при условии, если повторяются друг за другом....Т.е. должны получить:
   
       DTV	     TAGVAL
26.03.2015 15:57	0
26.03.2015 15:59	1
26.03.2015 16:02	0
26.03.2015 16:03	1
26.03.2015 16:07	0
26.03.2015 16:09	10
26.03.2015 16:11	0


TAGVAL имеет тип int, DTV - datetime

Как это осуществить? Distinct в традиционном варианте не подходит, т.к. находит уникальные значения.
Если это тема уже поднималась, то пожалуйста, направьте меня.
28 мар 15, 22:24    [17445604]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
row_number
Guest
Yegorich_555,

выбирай

declare @t table (DTV datetime, TAGVAL int)

set dateformat dmy

insert into @t(DTV,	     TAGVAL)
select '26.03.2015 15:57',	0 union all
select '26.03.2015 15:58',	0 union all
select '26.03.2015 15:59',	1 union all
select '26.03.2015 16:00',	1 union all
select '26.03.2015 16:02',	0 union all
select '26.03.2015 16:03',	1 union all
select '26.03.2015 16:04',	1 union all
select '26.03.2015 16:06',	1 union all
select '26.03.2015 16:07',	0 union all
select '26.03.2015 16:09',	10 union all
select '26.03.2015 16:10',	10 union all
select '26.03.2015 16:11',	0 union all
select '26.03.2015 16:12',	0

--select * from @t
---------------------------------------------------------------

;with cte as
(select *, row_number()over(order by DTV) as rn from @t)

select t1.DTV, t1.TAGVAL
from cte t1 left join cte t2 on t1.rn=t2.rn+1
where t1.rn=1 or t1.TAGVAL<>t2.TAGVAL

---------------------------------------------------------------

select min(DTV) as DTV, TAGVAL
from

(select *,
	row_number()over(order by DTV)-row_number()over(partition by TAGVAL order by DTV) as gr
from @t) a

group by gr, TAGVAL
order by 1
28 мар 15, 23:09    [17445757]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Yegorich_555
Member

Откуда:
Сообщений: 5
Спасибо. Правильно отработал 1-й вариант ) он мне и понравился. Тему можно закрывать!
29 мар 15, 01:44    [17445959]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Yegorich_555
Member

Откуда:
Сообщений: 5
Возникла ещё одна необходимость...Смысл в том, что нужно выводить не только каждое новое значение. Вот пример:

      DTV	     TAGVAL
26.03.2015 15:57	0
26.03.2015 15:58	0
26.03.2015 15:59	0
26.03.2015 16:00	0
26.03.2015 16:02	1
26.03.2015 16:03	1
26.03.2015 16:04	5
26.03.2015 16:06	5
26.03.2015 16:07	5
26.03.2015 16:09	0
26.03.2015 16:10	1
26.03.2015 16:11	0
26.03.2015 16:12	0


Должны получить первые и последние "не повторяющееся" значения:

      DTV	     TAGVAL
26.03.2015 15:57	0
26.03.2015 16:00	0
26.03.2015 16:02	1
26.03.2015 16:03	1
26.03.2015 16:04	5
26.03.2015 16:07	5
26.03.2015 16:09	0
26.03.2015 16:10	1
26.03.2015 16:11	0
26.03.2015 16:12	0


Сижу уже не первый час пытаясь использовать первый вариант предложенной выборки за основу. Но на SQL не знаю как реализовать подобное...
29 мар 15, 09:46    [17446166]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
invm
Member

Откуда: Москва
Сообщений: 9838
Yegorich_555
Должны получить первые и последние "не повторяющееся" значения
declare @t table (dtv datetime, tagval int);

set dateformat dmy;

insert into @t
values
('26.03.2015 15:57',	0),
('26.03.2015 15:58',	0),
('26.03.2015 15:59',	0),
('26.03.2015 16:00',	0),
('26.03.2015 16:02',	1),
('26.03.2015 16:03',	1),
('26.03.2015 16:04',	5),
('26.03.2015 16:06',	5),
('26.03.2015 16:07',	5),
('26.03.2015 16:09',	0),
('26.03.2015 16:10',	1),
('26.03.2015 16:11',	0),
('26.03.2015 16:12',	0);

select
 t.*
from
 @t t outer apply
 (select top (1) tagval from @t where dtv < t.dtv order by dtv desc) u(tagval) outer apply
 (select top (1) tagval from @t where dtv > t.dtv order by dtv) l(tagval)
where
 not (t.tagval = u.tagval and t.tagval = l.tagval) or u.tagval is null or l.tagval is null;

with x as
(
 select
  *,
  lag(tagval) over (order by dtv) as u_tagval,
  lead(tagval) over (order by dtv) as l_tagval
 from
  @t
)
select
 dtv, tagval
from
 x
where
 not (tagval = u_tagval and tagval = l_tagval) or u_tagval is null or l_tagval is null;
29 мар 15, 10:30    [17446219]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
row_number
Guest
;with cte as
(select *, row_number()over(order by DTV) as rn from @t)

select t1.DTV, t1.TAGVAL
from cte t1 
   left join cte t2 on t1.rn=t2.rn+1
   left join cte t3 on t1.rn=t3.rn-1
where	nullif(t1.TAGVAL,t2.TAGVAL) is not null 
   or	nullif(t1.TAGVAL,t3.TAGVAL) is not null
29 мар 15, 11:01    [17446289]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Yegorich_555
Member

Откуда:
Сообщений: 5
Спасибо! Выручили....
И вопрос к invm:
 lag(tagval) over (order by dtv) as u_tagval,
  lead(tagval) over (order by dtv) as l_tagval


на эту часть SQL server 2008 Express ругается!
29 мар 15, 11:08    [17446302]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Добрый Э - Эх
Guest
Yegorich_555
Спасибо! Выручили....
И вопрос к invm:
 lag(tagval) over (order by dtv) as u_tagval,
  lead(tagval) over (order by dtv) as l_tagval


на эту часть SQL server 2008 Express ругается!
сервер у тебя не той версии. lead/lag только с версии 2012 начинается...
29 мар 15, 11:14    [17446315]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Yegorich_555
Member

Откуда:
Сообщений: 5
Понял, спасибо!
29 мар 15, 11:15    [17446320]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Добрый Э - Эх
Guest
row_number,

зачем столько лефтов? кто мешал к первому row_number-у добавить второй с такимже PARTITION BY, но с обратной сортировкой. И на следующем уровне брать строки с rn1 = 1 or rn2 = 1
29 мар 15, 11:17    [17446326]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
row_number
Guest
Добрый Э - Эх
row_number,

зачем столько лефтов? кто мешал к первому row_number-у добавить второй с такимже PARTITION BY, но с обратной сортировкой. И на следующем уровне брать строки с rn1 = 1 or rn2 = 1
Честно говоря, не совсем понял, как это ...
Там же дело не только в крайних rn (которые действительно даст прямая и обратная сортировка и rn1 = 1 or rn2 = 1), а и в сравнении предыдущего и последующего значений ...

Можете на примере ТС показать?
declare @t table (DTV datetime, TAGVAL int)

set dateformat dmy

insert into @t(DTV,	     TAGVAL)
select '26.03.2015 15:57',	0 union all
select '26.03.2015 15:58',	0 union all
select '26.03.2015 15:59',	0 union all
select '26.03.2015 16:00',	0 union all
select '26.03.2015 16:02',	1 union all
select '26.03.2015 16:03',	1 union all
select '26.03.2015 16:04',	5 union all
select '26.03.2015 16:06',	5 union all
select '26.03.2015 16:07',	5 union all
select '26.03.2015 16:09',	0 union all
select '26.03.2015 16:10',	1 union all
select '26.03.2015 16:11',	0 union all
select '26.03.2015 16:12',	0
29 мар 15, 11:27    [17446345]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Добрый Э - Эх
Guest
row_number,

declare @t table (DTV datetime, TAGVAL int)

set dateformat dmy

insert into @t(DTV,	     TAGVAL)
values
('26.03.2015 15:57',	0),
('26.03.2015 15:58',	0),
('26.03.2015 15:59',	0),
('26.03.2015 16:00',	0),
('26.03.2015 16:02',	1),
('26.03.2015 16:03',	1),
('26.03.2015 16:04',	5),
('26.03.2015 16:06',	5),
('26.03.2015 16:07',	5),
('26.03.2015 16:09',	0),
('26.03.2015 16:10',	1),
('26.03.2015 16:11',	0),
('26.03.2015 16:12',	0);

select top 1 with ties 
       DTV, TAGVAL
  from (
         select t.*, 
                ROW_NUMBER() over(partition by tagval order by dtv) -
                ROW_NUMBER() over(order by dtv) as grp_id
           from @t t
       ) v
 order by case 
            when ROW_NUMBER() over(partition by grp_id, tagval order by dtv) = 1 
              or ROW_NUMBER() over(partition by grp_id, tagval order by dtv desc) = 1 
            then 1
            else 2
          end;


хотя, есть подозрение, что пара лефт-джойнов будет оптимальнее, чем 4-ре row_number-а...
29 мар 15, 17:40    [17447061]     Ответить | Цитировать Сообщить модератору
 Re: SQL выборка без последующих повторяющихся значений  [new]
Добрый Э - Эх
Guest
Добрый Э - Эх,

я бы ещё латеральный top 1 подзапрос попробовал бы ([CROSS | OUTER] APPLY)...
29 мар 15, 17:43    [17447068]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить