1

私はいくつかの野球の統計を分析しようとしていますが、単純なタスクのように見えるものを達成するのに苦労しています. 次の結果セットを見てください。

GAME_PK  REC_SEQ  BatterId  PlayNumber  EventType
287576   6        462101    1           single
287576   14       519048    2           single
287576   25       435079    3           strikeout
287576   26       435079    4           stolen_base_home
287576   28       435079    5           stolen_base_2b

PlayNumber 列は、ROW_NUMBER() OVER (ORDER BY GAME_PK, REC_SEQ) を使用して生成されています。残りは MLB 統計データベースから直接取得されます。REC_SEQ は、ゲーム内のイベントのシーケンス番号です。EventType は基本的に打席の結果です。

BatterId が変更された場合にのみ PlayNumber をインクリメントしたいと考えています。ただし、REC_SEQ の順序を尊重する必要があります。したがって、RANK または DENSE_RANK を使用できるとは思いませんが、必要なものに非常に近いようです。

結果セットを次のようにしたいと思います。

GAME_PK  REC_SEQ  BatterId  PlayNumber  EventType
287576   6        462101    1           single
287576   14       519048    2           single
287576   25       435079    3           strikeout
287576   26       435079    3           stolen_base_home
287576   28       435079    3           stolen_base_2b

どんな助けでも大歓迎です。

ありがとう!

編集: 打者は、ゲーム中に複数回表示できます。彼には、登場ごとに新しい PlayNumber が割り当てられる必要があります。基本的に、新しい打席ごとに新しい PlayNumber が必要です。

4

2 に答える 2

1

編集:これを達成できる唯一の方法は、どの連続したレコードがbatterIdを共有しているかを判断することによって、各グループの開始位置と終了位置を把握することです。これは、各グループの開始位置を決定するために、1 rownum だけオフセットしてレコードを結合することによって行われます。各グループ ( ) の開始点のコレクションを取得したら、GroupSets個々のレコードがどのグループに属しているかを判断して、正しい番号付けを生成できます。

with GroupSets as (
select
    row_number() over (order by s1.rec_seq) as rownum,
    s1.game_pk, s1.rec_seq, s1.batterid, s2.batterid as nextbatterid,
    s1.eventtype
from (select *, row_number() over (order by rec_seq) as rownum from stats) s1
left join (select rec_seq, batterid,
           row_number() over (order by rec_seq) as rownum from stats) s2
    on s1.rownum = s2.rownum + 1
where s1.batterid != s2.batterid or s2.batterid is null
)
select
    game_pk,
    rec_seq,
    batterid,
    (select max(rownum) from GroupSets gs where gs.Rec_Seq <= s1.rec_seq) as PlayNumber,
    eventtype
from
    stats s1;

デモ: http://www.sqlfiddle.com/#!3/a5e68/50


インターリーブを処理しない古いコード:

実際にはDENSE_RANK()関数がそれを行う必要があります。ただし、順序を制御するMIN(REC_SEQ)ために使用するには、BatterId グループごとの値をランク付けする必要があります。REC_SEQこのような何かがそれを行う必要があります:

select
    s1.game_pk,
    s1.rec_seq,
    s1.batterID,
    dense_rank() over (order by s2.rec_seq) as PlayNumber,
    s1.EventType
from
    stats s1
join
    (select batterid, min(rec_seq) rec_seq
     from stats group by batterid) s2 on s1.batterid = s2.batterid
order by
    rec_seq

デモ: http://www.sqlfiddle.com/#!3/0682e/4

于 2012-04-20T17:13:17.423 に答える
0

これは難しいですが、SQL Server では可能です。Oracle の分析関数を使用すると、これがはるかに簡単になります。

アイデアは次のとおりです。

  • 各ゲームで以前のプレイを取得できるように、厳密なシーケンス番号を追加します
  • これを使用して、特定のシーケンスでプレイが最初に打席になったときにフラグを追加します
  • ゲーム内でこれらを列挙して、プレイ番号を取得します
  • これを適切なグループを使用して統計に戻し、適切なプレイ番号を割り当てます

次のコードがうまくいくと思います:

with s_enum as 
(
   select s.*, ROW_NUMBER() over (partition by game_pk order by rec_seq) as Seq
   from stats
) s_cp as 
(
   select s.*, ROW_NUMBER() over (partition by game_pk, FirstInSeq) as BattingSeq
   from 
   (
     select s.*,
        (case when prev.BatterId = curr.BatterId then 1 else 0 end) as FirstInSeq
     from s_enum curr 
     left outer join s_enum prev
        on curr.game_pk = prev.game_pk 
        and curr.Seq = prev.Seq + 1
   )
)
select s.game_pk, s.batterid, s.rec_seq, MAX(bs.req_sec) as PlayNumber       
from stats s 
join
(
   select s.*
   from s_cp s
   where FirstInSeq = 1
) bs
  on s.game_pk = bs.game_pk 
  and s.batterid = bs.batterid 
  and s.rec_seq >= bs.req_sec
group by s.game_pk, s.batterid, s.rec_seq
于 2012-04-20T18:22:27.787 に答える