Подсчитывая, сколько раз в SQL Server изменяется значение boolean

У меня есть эта таблица:

     [SDate - DateTime]                 [Value] - Represents a boolean
    2010-11-16 10:10:00                    1
    2010-11-16 10:11:00                    0
    2010-11-16 10:12:00                    1
    2010-11-16 10:13:00                    1

Мне нужен запрос, чтобы подсчитать, сколько раз значение изменяется.

Например:

    2010-11-16 10:10:00                    0
    2010-11-16 10:11:00                    1
    2010-11-16 10:12:00                    0
    2010-11-16 10:13:00                    0
    2010-11-16 10:14:00                    1
    2010-11-16 10:15:00                    0
    2010-11-16 10:16:00                    1
    ...
                                       5 changes

    2010-11-16 10:10:00                    0
    2010-11-16 10:11:00                    0
    2010-11-16 10:12:00                    0
    2010-11-16 10:13:00                    1
    2010-11-16 10:14:00                    1
    2010-11-16 10:15:00                    1
    2010-11-16 10:16:00                    1
    ...                                       
                                        1 change

Ответ 1

Вы можете сделать это с помощью lag():

select count(*)
from (select t.*, lag(value) order by (sdate) as prev_value
      from table t
     ) t
where prev_value <> value ;

Ответ 2

Это должно работать и в более ранних версиях.

;WITH cte
     AS (SELECT Row_number()OVER(ORDER BY sdates) rn,*
         FROM   <tablename>)
SELECT Sum(CASE WHEN a.boolvalue = b.boolvalue THEN 0 ELSE 1 END)
FROM   cte a
       JOIN cte b
         ON a.rn = b.rn + 1 

Ответ 3

Пред-SQL Server 2012 решение:

declare @t table ( sdate datetime, value int )

insert into @t(sdate, value)
values
--('2010-11-16 10:10:00', 0),
--('2010-11-16 10:11:00', 1),
--('2010-11-16 10:12:00', 0),
--('2010-11-16 10:13:00', 0),
--('2010-11-16 10:14:00', 1),
--('2010-11-16 10:15:00', 0),
--('2010-11-16 10:16:00', 1)
('2010-11-16 10:10:00', 0),
('2010-11-16 10:11:00', 0),
('2010-11-16 10:12:00', 0),
('2010-11-16 10:13:00', 1),
('2010-11-16 10:14:00', 1),
('2010-11-16 10:15:00', 1),
('2010-11-16 10:16:00', 1)


;with t_with_seq as (
  select 
    t.*,
    ROW_NUMBER() OVER(ORDER BY t.sdate asc) as seq
  from @t t
)
select 
  COUNT(*) 
from t_with_seq r
  inner join t_with_seq r_next on r_next.seq = r.seq + 1
where r.value <> r_next.value