過去のレース結果を自分のデータベースにためようとすると、1枚の大きな表に全部入れたくなります。困るのは、欠場や失格、中止のレースが出てきたときです。結果のデータベースは、レース・出走・結果・払戻の4つに表を分けて、レースの番号(race_id)でつなぎます。
欠場・失格・中止は行を消さずに、空欄と「状態」の列で残します。こうしておくと、勝率の分母をあとから自分で選べます。
この記事では、4つの表の作り方と、普通でないレースの入れ方を書きます。ZEN BOAT LAB の研究用データベースで、2023〜2025年の168,252レースを数えた件数も載せます。データは、ZEN AI LAB が作って販売している自社ツールで集めました。
なお、過去のレースの結果を画面で見て調べるだけなら、公式のアプリや、過去のレースを検索できるアプリで足ります(7つを比べた記事は競艇のデータサイト・アプリ7つを比較)。この記事は、結果を自分でためて数えたい人向けの作り方です。
競艇のデータで何が数えられるかの全体は、競艇のデータの見方と集め方にまとめています。
表は4つ。「1行が何か」で分ける
表を分ける基準は1つです。その表の1行が、何を表しているか。競艇の結果なら、1行の意味は3種類しかありません。
- 1レース(いつ・どの場の・何レース目か)
- 1艇(そのレースの1号艇〜6号艇)
- 払戻の1つの組み合わせ(3連単の1-2-3、など)
この3種類で分けると、表は次の4つになります。数字は ZEN の研究用データベースの、2023〜2025年の行数です。
| 表 | 1行は何か | 3年の行数 |
|---|---|---|
| レース(races) | 1レース | 168,252 |
| 出走(race_entries) | 1艇。選手・モーターなど | 1,009,512 |
| 結果(race_results) | 1艇。着順・失格など | 1,009,512 |
| 払戻(payouts) | 券種×組み合わせ | 1,658,287 |
出走と結果は、どちらも1行=1艇です。それでも分けるのは、分かる時刻が違うからです。出走表はレースの前に、結果はレースの後に決まります。分けておくと、「レース前に分かっていたことだけ」で数えたいときに、結果の列が混ざりません。
レースの状態(普通に終わった・中止になった)も、結果の側に置きます。レースが終わるまで決まらないからです。ZEN のデータベースでは、結果の側にレースごとの表(race_outcomes)をもう1つ持っています。
4つの表は、race_id という1つの列でつなぎます。ZEN のデータベースでは「20250105_01_01」のように、日付・場の番号・レース番号を並べた文字です。同じレースなら、どの表でも同じ race_id になります。

1枚の表にまとめると、行が約10倍になる
では、4つを1枚にまとめるとどうなるか。出走・結果の6行に、そのレースの払戻の行をすべて付けた表を、件数だけ数えてみました。
3年分で9,949,722行です。結果の表の1,009,512行の、約10倍になります。払戻の行は1レースに7〜14行あり、そのぶん艇の行が複製されるからです。1レースは42〜84行になりました。
この表で、1号艇の1着を数えると904,001回です。実際の1号艇の1着は90,421回です。艇の行が払戻の行の数だけ重なるので、回数が約10倍になります。
厄介なのは、割合にするとほぼ同じ数字に見えることです。904,001回を1号艇の行の数で割ると54.51%です。中止を除いて1号艇の行で数えた54.50%と、ほとんど変わりません。割合だけ見ていると、表が壊れていることに気づけません。
払戻を3連単だけに絞ってつないでも、問題は残ります。
- 中止になった2,346レースは、払戻の行が無いので、表から消えます
- 同着で3連単の払戻が2つあった52レースは、1号艇の行が2回数えられます
消える行と、2回数える行が同時に出ます。1枚の表をやめて、払戻は払戻の表で数えるほうが確かです。
3年で、普通でないレースは約12レースに1回あった
対象は、ZEN の研究用データベースの2023年1月1日から2025年12月31日の168,252レースです。
中止・欠場・失格・同着・不成立・特払いのどれかがあったレースは、14,244レースでした。全体の8.5%で、約12レースに1回です。
| 起きたこと | 3年の件数 | 入れ方 |
|---|---|---|
| 中止 | 2,346レース | レースの状態を「中止」に。払戻は0行 |
| フライング欠場 | 3,959艇 | 着順は空。状態の列に残す |
| 出遅れ欠場 | 92艇 | 同上 |
| 欠場(そのほか) | 2,182艇 | 同上 |
| 失格(転覆など) | 8,290艇 | 着順は空。状態の列に残す |
| 同着 | 52レース | 払戻の行を2つ入れる |
| 不成立 | 577行 | 払戻の行は残し、金額は空 |
| 特払い | 107行 | 払戻の行は残し、状態を記録 |
同着の52は、3連単の払戻が2つあったレースの数です。不成立と特払いは、払戻の表の行の数です。不成立は226レースで、特払いは105レースで起きていました。
失格8,290艇の内訳は、転覆4,655・落水1,319・妨害910・エンスト903・不完走375・沈没96・そのほかの失格32です。
中止は、分母から外す
中止になったレースは、結果の表に6艇の行があります。ただし着順はすべて空で、払戻の行はありません。ZEN のデータベースでは、レースの状態の列が「CANCELLED」になっています。
1号艇の1着率を、中止を入れたまま数えると53.74%です。中止の2,346レースを外すと54.50%になります。走っていないレースは、1着ではなかったレースではありません。分母から外します。
欠場は、行を消さずに状態で残す
欠場には、フライング欠場・出遅れ欠場・それ以外の欠場の3つがあります。どれも着順の対象から外れ、その艇への投票は返還になります。3年で6,233艇、5,126レースでした。
欠場の艇の行は、消さないでください。ZEN のデータベースでは、欠場があったレースも、結果の表は必ず6行そろっています。行を消すと、「何艇立てのレースだったか」を行の数で数えたときに、取りこぼします。
欠場の1号艇を分母から外すかは、数える前に決めます。中止を外したうえで、欠場の1号艇も外すと、54.95%です。
失格は、返還されないので分母に残す
転覆や落水などの失格は、着順が付かなかった艇です。着順の列は空になります。欠場と違って、その艇への投票は返還されません。1着ではなかった艇として、分母に残すのが基本です。
中止と欠場を外した54.95%から、さらに失格の1号艇も外すと、55.26%に上がります。0.31ポイントの差です。失格の1号艇を分母から消すと、そのぶん1号艇が強く見えます。
どの分母を使うかは、問いで決まります。舟券の返還を除いた1着率を知りたいなら、中止と欠場を外した54.95%の数え方です。着順が付いた艇だけの数え方は、失格を「無かったこと」にするので、勝率には使いません。
Excel で同じ数え方をするときの式は、競艇のデータ分析をエクセルでに書きました。着順が空の行を分母に残す式と、外す式の両方を載せています。
同着は、払戻の行を2つにする
同着になると、同じ着順の数字が2艇に付きます。3年で、1着の同着が3レース、2着が6レース、3着が43レースありました。
同着のレースでは、3連単の払戻が2つの組み合わせに出ます。払戻を「1レース1行、3連単の列が1つ」の表にすると、2つめが入りません。払戻の表は、券種と組み合わせで1行にします。
不成立は、金額を0にしない
不成立は、その券種で払戻になる組み合わせが成立せず、全額返還になったものです。3年で577行あり、3連複226行・拡連複207行・3連単62行・複勝41行・2連複41行でした。
ZEN のデータベースでは、不成立の行の払戻金はすべて空です。0円で入っている行は1つもありません。0で埋めると、払戻金の平均や合計を出したときに、0円の払戻があったように数えてしまいます。行は残して、状態の列に「不成立」と書きます。
特払いは、払戻になる組み合わせを買った票が無かったときの払戻です。こちらは金額があります。3年で107行で、95行が単勝でした。
取得元が2つあると、値が食い違う
結果を2つの取得元から集めると、同じ艇の値が食い違うことがあります。ZEN のデータベースは、BOATRACE 公式サイトの競走成績のファイルと、有志が公開している非公式の API の2つから結果を取っています。
3年分で、着順の状態が食い違った艇は10,440艇ありました。BoatData の取り込みでは、公式のファイル側が区別の無い「失格」になっていた艇が、もう片方では「転覆失格」や「欠場」と分かれていたものです。そのうち2,182艇は、片方が「欠場」でした。
欠場と失格の違いは、分母に入れるかどうかに関わります。どちらを使うか決めずに上書きすると、数字が知らないうちに動きます。
ZEN のデータベースは、食い違いを別の表(value_conflicts)に記録しています。3年で35,588件です。どちらを採ったかも、1件ずつ残しています。自分で作るときも、取得元が2つあるなら、元の値を捨てない作りにしておきます。
自分で作るなら、SQLite で4つの表から
ここまでの考え方を、SQLite の表にすると次のようになります。列は最小限に絞りました。中止・欠場・同着・不成立を入れられる形です。
CREATE TABLE races (
race_id TEXT PRIMARY KEY,
race_date TEXT NOT NULL,
venue_code INTEGER NOT NULL,
race_no INTEGER NOT NULL
);
CREATE TABLE race_entries (
race_id TEXT NOT NULL REFERENCES races(race_id),
boat_number INTEGER NOT NULL,
racer_id INTEGER,
PRIMARY KEY (race_id, boat_number)
);
CREATE TABLE race_results (
race_id TEXT NOT NULL REFERENCES races(race_id),
boat_number INTEGER NOT NULL,
finish_position INTEGER,
finish_status TEXT NOT NULL,
PRIMARY KEY (race_id, boat_number)
);
CREATE TABLE race_outcomes (
race_id TEXT PRIMARY KEY REFERENCES races(race_id),
race_status TEXT NOT NULL
);
CREATE TABLE payouts (
race_id TEXT NOT NULL REFERENCES races(race_id),
bet_type TEXT NOT NULL,
combination TEXT,
payout_yen INTEGER,
popularity INTEGER,
payout_status TEXT NOT NULL,
UNIQUE (race_id, bet_type, combination)
);
- 出走と結果は「race_id と艇番」の組で1行です。同じ艇を2回入れようとすると、エラーで止まります
- 着順(finish_position)は空を許し、そのかわり状態(finish_status)は必ず入れます。「1着」「転覆失格」「フライング欠場」などです
- 払戻は「レース・券種・組み合わせ」の組で1行です。同着なら行が2つになります。不成立なら金額は空のまま、状態に「不成立」と入れます
1号艇の1着率を、中止と欠場を外して数えるSQLです。
SELECT COUNT(*) AS races,
SUM(r.finish_position = 1) AS wins,
ROUND(100.0 * SUM(r.finish_position = 1) / COUNT(*), 1) AS pct
FROM race_results r
JOIN race_outcomes o USING (race_id)
WHERE r.boat_number = 1
AND o.race_status <> 'CANCELLED'
AND r.finish_status NOT IN ('フライング欠場', '出遅れ欠場', '欠場');
失格の1号艇は分母に残ります。WHERE の2行を消せば、中止も欠場も入れた数え方になります。
このSQLは、架空の5レースを入れて実行し、答えを確かめました。1号艇が普通に1着・転覆失格・フライング欠場・中止・同着のレースで1着、の5つです。答えは3レース中2勝で、66.7%です。同じ5レースを、3連単の払戻とつないだ表で数えると、5行中3勝になりました。
表が壊れていないかは、行の数で確かめます。結果の表で、6行ではないレースを数えるSQLです。
SELECT COUNT(*) FROM (
SELECT race_id FROM race_results
GROUP BY race_id HAVING COUNT(*) <> 6
);
答えが0なら、どのレースも6艇そろっています。ZEN のデータベースの3年分では0でした。行を消してしまった抜けは、ここで見つかります。
表は作れても、ためるのが手間になる
表の形が決まっても、中身を入れるのが大仕事です。3年分で、結果の表だけで約100万行、払戻で約166万行あります。
公式のファイルを自分で落として表にする方法は、競艇の過去データをダウンロードする方法に書きました。ファイルの形から、欠場・失格・不成立を読み分けて、4つの表に振り分ける作業が毎日分つづきます。
その作業が重くなったら、集めてデータベースに入れるところをツールに任せる方法もあります。
集めてデータベースにするところを任せるなら
ZEN AI LAB の自社ツール BoatData Collector Pro は、この記事と同じ考え方の SQLite にためていきます。競艇の公開データを、期間と競艇場を選んでまとめて集める Windows 用のツールです。この記事の研究用データベースも、このツールで集めました。
- 出走表・展示/直前情報・結果・払戻を取得して、SQLite にためます。次からは新しい分だけを取ります
- 同梱のデータベース設計の資料では、表は15個(ほかに管理用が1つ)です。欠場の艇も6行そろえ、不成立は0円で埋めない作りです
- 取得元が2つで値が食い違ったときは、別の表に記録して、決めた優先順で採ります(同梱ドキュメント)
- Excel・CSV には、「レースごとに1行」「艇ごとに1行」の形で書き出せます
使う前に知っておいてほしいことです。
- 予想・買い目・自動投票の機能はありません。集めて保存し、出力するところまでです
- 公式サイトや BOATRACE とは関係のない、非公式のツールです。データの正確性は保証していません
- 無料版があります。取得できる期間は直近30日までです。製品版は期間を自分で選べます(保存できるのは2016年10月1日以降のレース。2026年11月に実際に取得して確かめた範囲)
くわしくはBoatData Collector Pro 無料版のページと、BoatData Collector Pro のページにあります。自分で取得の仕組みを作る場合の注意は、競艇のデータをAPIで取得するときの注意にまとめました。
競艇のデータを、何か月分も自分で集めて数えるなら

BoatData Collector Pro は、競艇の公開データを期間と競艇場を選んで集め、Excel・CSV に書き出す自社ツールです。予想や買い目は出しません。保存できるのは2016年10月1日以降のレースです。
- BoatData Collector Pro:6,000円(買い切り・note。ココナラでも6,000円)
- 分析版 BOAT DATA PRO:10,000円(ココナラ)。集めたデータを進入コース別・選手別などに集計する画面つき
- 無料版:直近30日まで(LINEで受け取り)
価格は2026年11月7日の表示です。変わることがあるので、買う前に各ページで確かめてください。Windows 11(64bit)用です。
確かめたことと、データでは分からないこと
確かめたことは、次のとおりです。
- 件数はすべて、研究用データベースを読み取り専用で開いて数えました。2023〜2025年の168,252レースです
- 1枚の表の行数は、表を実際には作らず、レースごとの行数の掛け算で数えました
- 記事のSQLは、架空の5レースを入れた SQLite で実行し、答えが合うことを確かめました
- 販売ページ2つは、2026年10月20日に開いて読みました
このデータでは分からないことは、次のとおりです。
- まだ確かめられていないこと:取得元が食い違った10,440艇について、どちらの値が正しかったかを、元の画面で1艇ずつ見てはいません
- 中止・欠場・失格の扱いは、ZEN の数え方です。ほかのサイトの勝率と比べるときは、数え方が同じとは限りません
- 記事のSQLを動かしたのは SQLite です。Access や MySQL など、ほかのデータベースはこの記事の範囲に入れていません
数字はどれも過去のレースを数えたものです。この先の結果を約束するものではなく、買い方の良し悪しを示すものでもありません。
まとめ
競艇の結果データベースは、1行の意味で表を分けて、race_id でつなぎます。欠場・失格・中止は、消さずに状態で残します。
- レース・出走・結果・払戻の4つの表を作り、結果の側にレースの状態を持たせます
- 欠場・失格は着順を空にして、状態の列に必ず書きます。不成立の払戻金は0にしません
- 数える前に、中止・欠場・失格を分母に入れるかを決め、数字の横に書いておきます
LAB 記録(読み飛ばしてかまいません)
- 対象は2023年1月1日〜2025年12月31日です。研究用データベース全体は、2023年1月1日〜2026年9月27日の1,366日・210,600レースです
- 2026年のぶん(42,348レース)は、あとで確かめるために残していて、件数だけを数えました
- 1号艇の1着率の4つの数え方の分母は、168,252(すべて)・165,906(中止を除く)です
- 続く2つは、164,543(中止と欠場を除く)・163,625(着順が付いた行だけ)です。分子はどれも90,421です
- 中止も入れた53.74%は、データベースの行をそのまま数えた値です。54.50%は、開催されたレースの1号艇の1着率です
- 165,906から欠場1,363と失格917を引くと163,626で、1つずれます。中止ではないレースに、状態が空の1号艇が1艇あるためです
- 1枚の表の1号艇の行は1,658,287行、そのうち1着の行は904,001行です。3連単だけでつなぐと165,958行で、165,906レースぶんです
- 中止の判定は、結果の側のレースの表(race_outcomes)の状態です
- レースの表(races)にも状態の列がありますが、ZEN のデータベースでは168,252レースすべてが「UNKNOWN」のままでした
- 番組を取り込んだ時点では決まらない列なので、確定した状態は結果の側だけに入っています。同じ意味の列が2か所にあるときは、どちらを使うかを決めておきます
- 欠場と失格は、着順の状態のコード(14〜16が欠場、7〜13が失格)で分けました。BoatData の同梱ドキュメント(異常系データのレポート)の分け方です
- 不成立は、3連単・3連複・拡連複などの券種ごとの行です。同じレースで2つ以上の券種が不成立になることがあります
- 14,244レースに入る同着は、払戻に関わる52レースだけです。4着・5着の同着(それぞれ47・43)は数に入っていません
- 中止の2,346レースには、艇の状態にフライング欠場が付いた艇が115艇あります。中止の形で分けると、その日の全レースが中止になった141日・1,692レース、途中のレースから最後まで中止になった129日・633レース、1レースだけの中止が21レースです(2026年11月6日に研究用データベースで集計)。天候や事故などの理由は、データベースにも公式の競走成績にも列が無いので、このデータでは分かりません
- 取得元の食い違いは、すべて公式の競走成績のファイルと非公式の API の間で、着順の状態に関するものでした
- 採ったのは、細かく分かれていた API 側の値です。公式の競走成績ファイル(手元にある2026年9月15日の1日分)を2026年11月6日に読むと、着順の欄に欠場は「K0」、失格は「S0」「S1」「S2」、フライングは「F」と書かれ、公式のファイルでも欠場と失格は区別されていました
- 集計の計画は、数える前に書きました。1回目の結果を見たあとに、1号艇の分母の4通りと、中止のレースの中身を足しています(追記した日付つき)


[…] 競艇の結果データベースの作り方: レース・出走・結果・払戻の4つの表の分け方と、欠場・中止・同着の数え方が分かる […]
[…] 同着があると払戻が2通り出ることなど、データとしての扱いは競艇の結果データベースの作り方に書いています。 […]