2009-08-10 8 views
3

データ分析に関する質問があります.T-SQLやスクリプトを使用して簡単に解決できると思いますが、巧妙なSQLソリューションがあるかどうかは疑問でした。問題は、SQLの行独立性の仮定を少し混乱させるということです。SQLで連続した重複レコードをカウントする

私は、ユーザーに関連付けられていると服従が注文した、例えば名前と値のペアで構成され、テーブルがあります。

 
ID  USERID VARIABLE  VALUE SUBMITTED 
3115 2287 votech05 2 2009-02-02 15:34:00 
3116 2287 comcol05 1 2009-02-02 15:34:00 
3117 2287 fouryr05 1 2009-02-02 15:35:00 
3118 2287 none05   2 2009-02-02 15:35:00 
3119 2287 ocol1_05 2 2009-02-02 15:44:00 
3120 2287 disnone   2 2009-02-02 15:45:00 
3121 2287 dissense 2 2009-02-02 15:49:00 
3122 2287 dismobil 3 2009-02-02 15:51:00 
3123 2287 dislearn 3 2009-02-02 15:51:00 
3124 2287 disment   3 2009-02-02 15:52:00 
3125 2287 disother 2 2009-02-02 15:55:00 
3126 2287 disrefus 7 2009-02-02 15:58:00 

私は最大の値と回数を決定できるようにしたいと思いますが同じ値のグループ(データがIDプライマリキーの順序になっている場合)。したがって、上記の例のために、私が持っているので、4値= 2が順番に登場し、わずか3つの値= 3は、私が報告したいと思う:指定したユーザーのための

 
USERID  VALUE  COUNT 
2287  2   4 

また、これは他のツールを使用してかなり迅速に行うことができますが、データセットがかなり大きく(約7,500万レコード)頻繁に変更されるため、この問題をクエリで解決できることがうまくいくでしょう。私はあなたがその連続する値の各グループに「頭」番号を割り当てることによって行うことができます(コメントの後編集)SQL Server 2005の

+0

Good title edit、Brian。ありがとう。私は調査研究者のために働き、彼の言葉は私がその問題について考えていたやり方を偏らせていました。 –

答えて

3

で働いています。その後、各行のヘッド番号を選択し、ヘッドごとに集計を行います。

ここでCTEの読みやすさのために、例を示します

WITH 
OrderedTable as (
    select value, rownr = row_number() over (order by userid, id) 
    from YourTable 
    where userid = 2287 
), 
Heads as (
    select cur.rownr, CurValue = cur.value 
    , headnr = row_number() over (order by cur.rownr) 
    from OrderedTable cur 
    left join OrderedTable prev on cur.rownr = prev.rownr+1 
    where IsNull(prev.value,-1) != cur.value 
), 
ValuesWithHead as (
    select value 
    , HeadNr = (select max(headnr) 
       from Heads 
       where Heads.rownr <= data.rownr) 
    from OrderedTable data 
) 
select Value, [Count] = count(*) 
from ValuesWithHead 
group by HeadNr, value 
order by count(*) desc 

これが出力されます:最初の行のみを選択する

Value Count 
2  4 
3  3 
1  2 
2  1 
2  1 
7  1 

使用 "トップ1"。

はここでテストデータを作成するために、私のクエリです:

create table YourTable (
    id int primary key, 
    userid int, 
    variable varchar(25), 
    value int 
) 
insert into YourTable (id, userid, variable, value) values (3115, 2287, 'votech05', 2) 
insert into YourTable (id, userid, variable, value) values (3116, 2287, 'comcol05', 1) 
insert into YourTable (id, userid, variable, value) values (3117, 2287, 'fouryr05', 1) 
insert into YourTable (id, userid, variable, value) values (3118, 2287, 'none05', 2) 
insert into YourTable (id, userid, variable, value) values (3119, 2287, 'ocol1_05', 2) 
insert into YourTable (id, userid, variable, value) values (3120, 2287, 'disnone', 2) 
insert into YourTable (id, userid, variable, value) values (3121, 2287, 'dissense', 2) 
insert into YourTable (id, userid, variable, value) values (3122, 2287, 'dismobil', 3) 
insert into YourTable (id, userid, variable, value) values (3123, 2287, 'dislearn', 3) 
insert into YourTable (id, userid, variable, value) values (3124, 2287, 'disment', 3) 
insert into YourTable (id, userid, variable, value) values (3125, 2287, 'disother', 2) 
insert into YourTable (id, userid, variable, value) values (3126, 2287, 'disrefus', 7) 
+0

正確には、私は各値の合計カウントを望んでいないので、それらがどのようにクラスタ化されているか、つまり2,1,2,2,1,1,2,2,2,2,1,1が返されます値= 2、カウント= 4、7ではなく。 –

+0

+1、編集後に動作し、カーソルを使用するより効果的です! –

+0

これは有望そうです。私はそれを見てみましょう。私はそれを助けることができれば、カーソルを使用したくないでしょう(これらのタイプの相互依存問題では、CTEを使用してもパフォーマンスは同じになる可能性があります)。ありがとう。 –

2

これが最良のカーソルで解決これらの問題の一つであってもよいです。これを試してみてください。それは近いはずですが、簡単にするためにサンプル・データをCREATE TABLE文とINSERT文で指定していないため、テストされていません。

declare @userid int 
set @userid = 2287; 
declare C cursor fast_forward for 
select VALUE from T 
where USERID = @userid 
order by ID; 

declare @value int, @prevvalue int; 
declare @runcount int, @runlongest int; 
set @runlongest = 0; 
declare @valuelongest int; 
open C; 
fetch next from C into @value; 
while @@fetch_status = 0 begin 
    if @value = @prevvalue set @runcount = @runcount + 1 else set @runcount = 1; 
    if @runcount > @runlongest begin 
    set @runlongest = @runcount; 
    set @valuelongest = @value; 
    end; 
    set @prevvalue = @value; 
    fetch next from C into @value; 
end; 
select @userid as USERID, @valuelongest as VALUE, @runlongest as [COUNT]; 

close C; 
deallocate C; 

75M行では高速ではありませんが、遅すぎるとは限りません。実行が非常に長く、適切なインデックスがある場合は、tempテーブルのrow_numberに番号を付けてから、一度に実行をジャンプするWHILEループを使用するとより効果的です。見てみる価値があると思ったら教えてください(もし可能であれば、サンプルデータでCREATE TABLEステートメントとINSERTステートメントを投稿してください)。私は次のように動作するはずだと思い、それをテストすることなく、

0

ROW_NUMBER()(IDによる値のため、ユーザーIDによってパーティション)を超える

これは単に最高row_nunber

で1を選択し終わったら

これがうまくいったらお知らせください!

ありがとう、Edi

+0

Edi、 row_number()は連続した値を非連続の値と同じ方法で処理するため、機能しません。そこにいくつの値があるのか​​だけではなく、一連の値がここで問題になります。 –

+0

so soesこれは順序が定義できないことを意味しますか?申し訳ありませんが、私はこれを取得しません。 –

関連する問題