2016-07-01 1 views
1

クエリを作成しようとしています。連続した行のサブセット(ギャップとアイランド)の最小値と最大値を求める

入力は、 'name'の一意の値ごとに1から始まり、 'act'のエントリの指定されたシーケンスを定義する列 'rn'のrownumberによって順序付けられます。列 'act'では、複数の発生で> sleep <と> wake <の2つの値を保持します。目標は、starttとenddの最小値と最大値をそれらの値のいずれかの連続する各行のセットごとに見つけることです。

これは入力しなければならない:

name  act  rn  startt endd 
---------- ---------- ------ ------ ------ 
jimmy  sleep  1  1  3 
jimmy  wake  2  4  7 
jimmy  wake  3  8  10 
jimmy  sleep  4  11  13 
karen  wake  1  1  4 
karen  sleep  2  5  7 
karen  wake  3  8  9 
karen  wake  4  10  12 
karen  wake  5  13  14 
karen  sleep  6  15  17 
karen  sleep  7  18  20 

所望の出力:

name  act  startt endd 
---------- ---------- ------ ------ 
jimmy  sleep  1  3  
jimmy  wake  4  10  
jimmy  sleep  11  13  
karen  wake  1  4  
karen  sleep  5  7  
karen  wake  8  14  
karen  sleep  15  20 

入力のソースがさらに列を提供しません。この例では、各サブセットのメンバー数が非常に高くなる可能性があります。

私はさまざまな集約方法を試しましたが、どれもうまくいきませんでした。私はLEADLAGGを使っていると信じています。そしてそれ以上のトリッキーは私をそこに連れていくかもしれませんが、それは非常に不愉快なようです。私は、各サブセットを区別すること、すなわち、そのすべてのメンバーに固有の識別子を作成することが重要であるという考えを持っている。これにより、minmaxの集約が簡単になります。たぶん私は間違っています。多分それは不可能です。多分自己結合。多分再帰的なcte。知りません。

だから誰でもこの方法を知っていますか?ヘルプは非常に感謝しています。

UPDATE:

ゴードン・リノフ、shawnt00とコメントし、他の貢献に感謝します。あなたの助言を得て、私はロジック閉鎖のツールボックスに大きなギャップを感じます。興味のために

declare @t table (
    name nvarchar(10) 
    ,act nvarchar (10) 
    ,startt smallint 
    ,endd smallint 
    ) 

insert into @t (
    name 
    ,act 
    ,startt 
    ,endd 
    ) 
values 
    ('jimmy','sleep', 1,3) 
    ,('jimmy','wake', 4,7) 
    ,('jimmy','wake', 8,10) 
    ,('jimmy','sleep', 11,13) 
    ,('karen','wake', 1,4) 
    ,('karen','sleep', 5,7) 
    ,('karen','wake', 8,9) 
    ,('karen','wake', 10,12) 
    ,('karen','wake', 13,14) 
    ,('karen','sleep', 15,17) 
    ,('karen','sleep', 18,20) 

; --- all rows, no aggregating 
with 
cte as (
select 
    name 
    ,act 
    ,row_number() over (partition by name order by name,startt) rn 
    ,row_number() over (partition by name, act order by name,startt) act_n 
    ,startt 
    ,endd 
from 
    @t) 
select 
    name 
    ,act 
    ,startt 
    ,endd 
    ,rn 
    ,act_n 
    ,rn - act_n diff 
from 
    cte 
order by 
    name 
    ,rn 

;--- aggregating for the desired ouput 
with 
cte as (
select 
    name 
    ,act 
    ,row_number() over (partition by name order by name,startt) rn 
    ,row_number() over (partition by name, act order by name,startt) act_n 
    ,startt 
    ,endd 
from 
    @t) 
select 
    name 
    ,act 
    ,min(startt) startt 
    ,max(endd) endd 
    ,min(rn)  min_rn 
    ,max(rn)  max_rn 
from 
    cte 
group by 
    name 
    ,act 
    ,rn - act_n 
order by 
    name 
    ,min(rn) 
+0

これはギャップと諸島の問題です。それを探して、解決策を見つけることができます。または、このページの第5章PDFを参照してください。https://www.manning.com/books/sql-server-mvp-deep-dives – mheptinstall

+0

したがって、どのRDBMSですか? – Strawberry

+0

enddとstarttの違いがグループ化されている場合は常に1ですか?または、これらのサンプルセットだけで、次のセットは名前の変更に基づいていますか? –

答えて

3

あなたが同様の行の連続したグループを検索して、凝集したいです。私は、行番号のアプローチの違いを好き:

select name, act, min(startt) as startt, max(endd) as endd 
from (select i.*, 
      row_number() over (partition by name, act order by rn) as seqnum_na, 
      row_number() over (partition by name order by rn) as seqnum_n 
     from input i 
    ) i 
group by (seqnum_n - seqnum_na), name, act; 

あなたはこのサブクエリが何をするかを見ることでどのように動作するかを確認することができます。

+0

フレーミングウィンドウ機能をチェックアウトします。あなたはこれを私がワンショットで行うことができるはずです。 https://msdn.microsoft.com/en-us/library/ms189461.aspx –

+1

@MatthewWhitedおそらく、あなたはその解決策で別の答えを書くことができます。私はまだいくつかの時間を試しても行方不明の概念を理解していない。 –

+0

私はフレームであまりにも早く話したと思います。私は統計のためにそれらを使用しましたが、これはわずかに異なります。再帰的なCTEのように見えます。 (またはこの例のようなグループ)...しかし、私は私の口から私の足を引っ張って私は答えを投稿します。 –

1

これは、rn番号に空白がないことを前提としているため、再度数値を計算しません。

with T2 as (
    select *, row_number() over (partition by name, act order by rn) as grp_rn 
    from T 
) 
select name, act, min(startt) as startt, max(endd) as endd 
from T2 
group by name, act, rn - grp_rn 
order by name, startt; 

http://rextester.com/CCQJJ93990

これは典型的なギャップと島々クエリです。ここでの重要な点は、行のクラスターを持つ場合、2つの異なる番号がステップで増加し、その差がクラスターの定数であることを意味します。この違いは、あなたがリストを下っていくにつれて増加します。

+0

あなたの説明をありがとうございます。このトリックは素晴らしいです。また、違いの増加に良いヒント。 –

関連する問題