4

特定の日付にイベントが発生したかどうかに基づいて、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 である必要があります (2 の 1 つのグループ、次に 2 の別のグループ、最後に 1 で終了します)。

うまくいけば、上記の例は私が何をしようとしているのかを示しています。しばらく探していましたが、探しているものを簡潔に説明するのが難しく、関連するものが何も見つかりませんでした。

前もって感謝します、

ジョシュ

4

3 に答える 3

3

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
于 2011-02-17T09:04:47.067 に答える
2

これは、「島」問題の変種です。私の最初の答えは、Itzik Ben Gan の二重の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

2 番目の回答では、データを 1 回通過する必要があります。動作が保証されているわけではありませんが、多くの人が問題なく文字列を連結するために使用している手法と同じ原理に基づいています。

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)
于 2011-02-17T09:32:36.277 に答える
1

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)
于 2011-02-17T09:06:19.140 に答える