SQL Server - подсчет количества изменений атрибута в наборе данных (не одновременно) - PullRequest
4 голосов
/ 17 февраля 2011

У меня есть запрос, который возвращает 1 или 0 в зависимости от того, произошло событие в определенную дату или нет.Это упорядочено по дате.По сути, простой набор результатов:

Date         |  Type
---------------------
2010-09-27      1
2010-10-11      1
2010-11-29      0
2010-12-06      0
2010-12-13      1
2010-12-15      0
2010-12-17      0
2011-01-03      1
2011-01-04      0

Теперь я хотел бы подсчитать количество отдельных, несовпадающих экземпляров '0', то есть подсчитать, сколько разныхгруппы 0 появляются.

В приведенном выше примере ответом должно быть 3 (1 группа из 2, затем другая группа из 2, затем, наконец, 1 до конца).

Надеюсь, приведенный выше пример иллюстрирует то, что япытаюсь добраться до.Я долго искал, но мне сложно кратко описать то, что я ищу, и, следовательно, я не нашел ничего актуального.

Заранее спасибо,

Джош

Ответы [ 3 ]

3 голосов
/ 17 февраля 2011

Вы можете дать каждой строке номер в CTE.Затем вы можете присоединиться к таблице на себя, чтобы найти предыдущий ряд.Зная предыдущую строку, вы можете суммировать, сколько раз предыдущая строка была равна 1, а текущая строка равна 0. Например:

; with NumberedRows as
        (
        select  row_number() over (order by date) as rn
        ,       type
        from    YourTable
        )
select  sum(case when cur.type = 0 and IsNull(prev.type,1) = 1 then 1 end)
from    NumberedRows cur
left join    
        NumberedRows prev
on      cur.rn = prev.rn + 1
2 голосов
/ 17 февраля 2011

Это вариант проблемы «островов». Мой первый ответ использует двойной трюк Ицик Бен Ган row_number, чтобы эффективно идентифицировать смежные группы данных. Комбинация Type,Grp идентифицирует каждый отдельный остров в данных.

Подробнее о различных подходах к решению этой проблемы вы можете прочитать здесь.

;WITH T AS (
    SELECT  *,
            ROW_NUMBER() OVER(ORDER BY Date) -
            ROW_NUMBER() OVER(PARTITION BY Type ORDER BY Date)  AS Grp
    FROM    YourTable
)
SELECT  COUNT(DISTINCT Grp)
FROM    T
WHERE Type=0

Мой второй ответ требует одного прохода через данные. Он не гарантированно работает, но работает по тому же принципу, что и метод, который многие люди успешно используют для объединения строк без проблем.

DECLARE @Count int = 0

SELECT @Count = CASE WHEN Type = 0 AND @Count <=0 THEN -@Count+1 
                     WHEN Type = 1 AND @Count > 0 THEN - @Count
                     ELSE @Count END

FROM YourTable
ORDER BY Date

SELECT ABS(@Count)
1 голос
/ 17 февраля 2011

Посмотрите на этот пример, используя Sql Server 2005 +

DECLARE @Table TABLE(
        Date DATETIME,
        Type INT
)

INSERT INTO @Table SELECT '2010-09-27',1
INSERT INTO @Table SELECT '2010-10-11',1
INSERT INTO @Table SELECT '2010-11-29',0
INSERT INTO @Table SELECT '2010-12-06',0
INSERT INTO @Table SELECT '2010-12-13',1
INSERT INTO @Table SELECT '2010-12-15',0
INSERT INTO @Table SELECT '2010-12-17',0
INSERT INTO @Table SELECT '2011-01-03',1
INSERT INTO @Table SELECT '2011-01-04',0

;WITH Vals AS (
    SELECT  *,
            ROW_NUMBER() OVER(ORDER BY Date) ROWID
    FROM    @Table
)
SELECT  v.*
FROM    Vals v LEFT JOIN
        Vals vNext ON   v.ROWID + 1 = vNext.ROWID
WHERE   v.Type = 0
AND     (vNext.Type = 1 OR vNext.Type IS NULL)
...