2016-03-29 10 views
0

私はこの質問が繰り返されたかどうかわかりませんが、回答がある場合は「回答済み」の質問に従ってガイドしてください。そして、私はこのクエリのために何が適切なタイトルかもしれないのか分かりません。方法:特定の複雑なグループ化クエリ

は、私は私のSQL Serverで、次のデータを持っている2008 R2

|Date    |Status  | 
|------------------|------------| 
|29-Mar-2016 07:30 |X   | 
|29-Mar-2016 07:31 |Y   | 
|29-Mar-2016 07:32 |Y   | 
|29-Mar-2016 07:33 |Y   | 
|29-Mar-2016 07:34 |Y   | 
|29-Mar-2016 07:40 |X   | 
|29-Mar-2016 07:43 |Z   | 
|29-Mar-2016 07:45 |Z   | 

SQLクエリの

|Start Date  | End Date   |Status  | 
|------------------|------------------|-----------| 
|29-Mar-2016 07:30 |29-Mar-2016 07:31 |X   | 
|29-Mar-2016 07:31 |29-Mar-2016 07:34 |Y   | 
|29-Mar-2016 07:40 |29-Mar-2016 07:43 |X   | 
|29-Mar-2016 07:43 |29-Mar-2016 07:45 |Z   | 

任意の提案を以下のようである私は期待していた結果。

+2

'gaps-and-islands 'のように見えますが、必要なロジックが明確ではありません。なぜ「終了日」は「開始日」と同じグループから取られ、時には次のグループから取られるのでしょうか? –

+0

@VladimirBaranov日付はミリ秒単位で取得されます。グループ化された「Y」のデータの最後の行が終了日となり、「X」のグループ化されたデータの開始が開始日となる。 – aioracle

答えて

1
DECLARE @TEMP AS TABLE(
    [Date] DATETIME, 
    [Status] VARCHAR 
) 

INSERT INTO @TEMP VALUES('29.03.2016 07:30','X') 
INSERT INTO @TEMP VALUES('29.03.2016 07:31','Y') 
INSERT INTO @TEMP VALUES('29.03.2016 07:32','Y') 
INSERT INTO @TEMP VALUES('29.03.2016 07:33','Y') 
INSERT INTO @TEMP VALUES('29.03.2016 07:34','Y') 
INSERT INTO @TEMP VALUES('29.03.2016 07:40','X') 
INSERT INTO @TEMP VALUES('29.03.2016 07:43','Z') 
INSERT INTO @TEMP VALUES('29.03.2016 07:45','Z') 

SELECT * FROM @TEMP 

;WITH TEMP(n,d,s) 
AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY [Date]),[Date],[Status] 
    FROM @TEMP 
), StatePeriods(n,T_n,T_d,T_s,TL_n,TL_d,TL_s,TR_n,TR_d,TR_s) 
AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY T.d),T.n,T.d,T.s,TL.n,TL.d,TL.s,TR.n,TR.d,TR.s 
    FROM TEMP AS T 
    LEFT JOIN TEMP AS TR ON T.n = TR.n-1 
    LEFT JOIN TEMP AS TL ON T.n-1 = TL.n 
    WHERE T.s <> TR.s OR T.s <> TL.s OR TR.s IS NULL OR TL.s IS NULL 
) 
SELECT SP1.T_n,SP1.T_d,SP1.T_s,SP1.TL_d,SP1.TL_s,CASE WHEN SP1.T_s = SP3.T_s THEN SP3.TR_d ELSE SP3.T_d END 
FROM StatePeriods AS SP1 
LEFT JOIN StatePeriods AS SP2 ON SP1.n-1 = SP2.n 
LEFT JOIN StatePeriods AS SP3 ON SP1.n+1 = SP3.n 
WHERE NOT (SP1.T_s=SP2.T_s AND SP1.TL_s IS NOT NULL AND SP1.TR_s IS NOT NULL) 

そして、あなたは、これは非常にリソース集中型ソリューションであり、最初または最後の行に

を絞り込むことができます。しかし、 'WITH'の代わりに一時テーブルを使うことができます

+0

ありがとうございます。チャームのような作品!私はこのクエリにtimediffを追加しました。どのように私はこれに追従クエリがすぐにそれを投稿します。 – aioracle