Upgrade to Pro — share decks privately, control downloads, hide ads and more …

プロ野球をデータモデリングしてみたら沼だった件 / Baseball ERD Modeling to be obsessed

プロ野球をデータモデリングしてみたら沼だった件 / Baseball ERD Modeling to be obsessed

Baseball Play Study mini〜野球でデータモデリング(BPStudy#187)
https://bpstudy.connpass.com/event/277381/

YUMOTO Michitaka

March 29, 2023
Tweet

More Decks by YUMOTO Michitaka

Other Decks in Technology

Transcript

  1. YUMOTO Michitaka Hello! 2 • ゆもと みちたか(ござパイセンというHNで生きてます) • 1979年生まれです。松坂世代。 •

    GoTheDistanceというブログを書いてます。たまに。 • 新卒SIer→雑貨製造業で内製→独立してもうすぐ7年。 • Flutter/React/T3 Stack等のフロントエンド好き • やきうを愛する東京ヤクルトスワローズのファン!
  2. BPStudy History • BPStudy#79(野球) • BPStudy#91(野球) • BPStudy#92 • BPStudy#100(野球)

    • BPStudy#103(野球) • BPStudy#108 • BPStudy#112(野球) 3 • BPStudy#115(野球) • BPStudy#122 • BPStudy#124(野球) • BPStudy#127(野球) • BPStudy#140(登板回避) • BPStudy#142 • BPStudy#185(Flutter) • BPStudy#187(NEW)
  3. データモデリングはエンティティの抽出が9割 6 目に見えないソフトウエアは概念を明文化して共有するのだ ➔ データモデリングのコアは「エンティティ」の抽出。 ➔ 自分たちが作ろうとしているソフトウエアで取り扱うデータに名前をつけ、実態として認識 できるように命名付けた概念=エンティティ。 名称 内容

    例(ホテルの予約システム ) ヒト そのシステムを利用する人達 社員(役職・部門等)、取引先、得意先、ア ルバイト。 モノ システムで取り扱う資産・サービス プラン・予約・お部屋・設備・カレンダー コト システムを通じて行われる行動・イベント 予約受付・問い合わせ・オンライン決済・ キャンセル・空き状況を確認する
  4. 正規化 is 何 7 ライフサイクルが違うものは別のテーブルに切り出せ ➔ 一番良くわからなかった概念が、正規化だった。今でもちょっとあやしい。 ➔ 正規化における「重複を排除せよ」は 「ライフサイクル」の違うエンティティは必ず分離しろ

    でよくない?よくなく なくなく なくなく ない? ➔ それを進めていけば、イミュータブル・データモデリングへと繋がるのでは? ➔ 予約のデータを作るのにプランが予約の中に入ってし まったら、新しい予約を作る時に必ず新しいプランが作ら れてしまう。 ➔ 予約とプランは別々のライフサイクルを持っているので、 エンティティ分けよう。 ➔ こう考えれば勝手に第3正規形までいくだろ多分
  5. ざっとこんだけのエンティティが必要だな 10 試合 開催日時、場所、経過時間、予告先発、勝利投手、敗戦投手、セーブ等 チームと選手 チーム変わったりするよね。うん。それと選手は全員要るよね 打順 ラインアップですね。選手は当然交代するので。 ポジション 1〜9、及びDH。Enumでアプリ側で持っても良さげ。増減がないので。

    スコアボード イニング毎の得点、ヒット数等を掲載する必要がある。 1球速報 1球ごとにカウント変わり得るので。球数も出す必要がある。 交代履歴 投手及び野手の交代の履歴。 試合毎の成績 打者成績(打率とHRはマスト)と投手成績 開催日程 ペナントレースの開催日程に応じて成績表を出す必要があるため。
  6. 試合エンティティを考える 11 - - 開催日時 - 開催球場 - ホームチームID -

    ビジターチームID - ホーム予告先発 - ビジター予告先発 - ホーム得点数 - ビジター得点数 - 勝利投手 - 敗戦投手 - セーブ - 観客数 - 試合時間 試合エンティティ - ID - 名称 球場 - ID - チーム名 - 所属リーグ チーム - ID - 登録名 - ポジション - 背番号 プレイヤー ➔ 正規化を崩すべきか悩む所 ◆ 球場名はネーミングライツで同じ場所でも呼 称が変わる為。チーム名も同様。 ◆ シーズン年度と名称だけを持つエンティティ 作って、シーズン年度でWHERE? ➔ チーム・プレイヤー・球場はマスタから参照すべき だ。固定値を埋めることは考えにくい。 ➔ セーブは NULL許容カラムしかない? ➔ 審判も球審・塁審 x 3 が必要だ。1 : 1 の別エンティ ティ? カラム追加? ➔ リクエストの残り回数も管理が必要だとすると、どこ に保管すべきデータ?
  7. スコアボードエンティティを考える 12 - 試合ID - イニング数 - チームID - 得点

    - 四球 - 安打数 - エラー イニング ➔ スコアボードはテーブルで表現できない気がしている。イニングの集合体がスコアボードな ので、SQLでデータ取得→アプリ側でスコアボードのUIに沿ったデータを作るしかないので は? ➔ 仮にスコアボードテーブルを作る場合、どういう設計にしていくのか??? ➔ イニング毎に記録する数字が多いので、縦に持つしかない。 ➔ ノーゲーム・雨天コールド・延長戦等、消化するイニング数が試合によって異 なる。その点を踏まえても、イニングを積むしかなさそう。 ➔ 裏の攻撃がなく試合が終わることが結構ある。 9回表で試合終了する ケースには「X」がスコアボードにつくけど、まさか DB側にXを保存するわ けにもいかんだろ・・・
  8. カウントとランナー表示を考える 13 ➔ カウントは1球毎に異なる場合もあれば、4球投げても同じこともある。 ➔ ストライクとボールカウントは0になり、アウトカウントも3つ目で0になる。 ➔ 最大要素数が決まっているので単純に配列で持てば良さそう。 ➔ 状況によってリセットされる性質があるので、

    SQLでカウント表示を表現するのは出来ない ように思うけど、まさか方法があるんだろうか・・・? ➔ ランナーもリセットされる。塁とランナー存在フラグを持つオブジェクトを作り、 1塁2塁3塁の 3つのフィールドを持たせるだけで良さそうだが、改良の余地はあるか???
  9. 成績表示を考える 14 ➔ 横持ちが簡単そうでいいけど、UPDATEの嵐になるデータ操作は正しいのか? - 試合ID - プレイヤーID - 球数

    - 奪三振 - 与四球 - 与死球 - 失点 - 自責点 - アウトカウント 投球履歴 ➔ 横に持った場合、1球投げる毎に投球数や被安打を更新することにな る。すげーミュータブルなデータになってしまう。 ➔ 1球投げる毎にレコードを追加して縦に持った場合、歯抜けなデータの 持ち方になるけど、GroupByで頑張ればできそう。 ➔ 横持ちした場合、被安打や打者等はただインクリメントするだけだけど、 縦持ちした場合、三振とかヒットのような結果はどこで保存すべきなんだ ・・・?!
  10. 野手成績表示を考える 15 ➔ このUI作るの大変じゃないか・・・? ➔ 打数と打席数が一致しない。四死球は打数にカウントされない。 ◆ 第1打席は三振、第2打席は四球等の履歴は、別テーブルで保持する必要があります。 ➔ 代走・守備固めでの出場があるので、代走の場合は盗塁だけ、守備固めの場合は失策のみが計

    上されるケースがありえます。打席が与えられないケースもあるので、打席の履歴は別。 ➔ 選手が起用される毎に 1レコード増やし、初期値は打率以外は全部 0。打率はこのテーブルの最後 の1件を取り、プレイが完結したら UPDATEしていく以外、ちょっと思いつかなかった。
  11. The die is cast. Let’s go for October! Thanks! 17

    あかん、優勝してしまう ◉ @gothedistance ◉ [email protected]