となかい一朗さんの競馬日記

競馬 SQLでビッグデータ分析-ACCESSのFORMから回収率分析(5)

 公開

484

SQLについて詳しく説明しようとすると、なかなか先に進みません・・・。
しかし、大事なことなので、投稿の密度を濃くして対応したいと思います(おかげで最近、新しい分析ができていないのですが・・・)。

前回までに説明したSQLの知識で、少なくとも、クエリ上で、勝率を出す、以下のSQL(10月29日のコードの中に出てくるSELECT文のもととなるSQL)を理解できる前提ができたと思います。

「SELECT [対象のフィールド名] AS 区分,count(*) AS n, count(RaceUma.確定着順 =1 or null) AS 勝数, int(count(RaceUma.確定着順 =1 or null)/count(*)*1000)/10 AS 勝率 FROM RaceUma GROUP BY [対象のフィールド名] 」

[対象のフィールド名] に、RaceUmaのフィールド名を入れて、クエリにかけてやれば、そのフィールドの各値ごとの勝率が出るはずですね。

いくつか解説を加えると・・・
・「AS ~」というのは、抽出フィールドの名前を、AS以下の名前に付け替えています。

・左から、1.区分(対象のフィールド名)、2.n(データの数)、3.勝数(1着の回数)、4.勝率(1着の回数をデータ総数で割って、小数点1位まで表示のパーセンテージ表示にしている) です。

・集計関数のCount(条件)という書き方だと、条件のうしろに 「or null」とつけないと、確定着順に数字が入っているものは全部数えて、条件指定が意味なくなってしまいます。詳しいことはググれば解説出ていると思いますけど、おまじないだと思って、集計関数COUNTで、条件を指定するときは、「or null」とつけると覚えるので十分だろうと思います。

・「*1000」は、1000をかけましたという意味です。int( )は、その小数点以下をなくして整数にする関数です。それを10で割って、小数点1位までを表示したパーセンテージの数字を出しています。


さて、しかし競馬には、勝率よりも大事な数字があります。それは回収率です。

前回、回収率の計算まではしていませんでした。それは、「つくれます Access版 for JVDL 5.09.2a」は、RaceUmaテーブルに、配当に関する情報が無いからです。

配当に関する情報は、じゃあ、どこにあるのかと言えば、Raceテーブルにあります。
Raceテーブルを見ると、単勝馬番1~単勝馬番3までと、単勝払戻金1~単勝払戻金3まで。それから、複勝は複勝馬番1から複勝馬番5までと、複勝払戻金1~複勝払戻金5までに該当馬と配当の情報が入っています。単勝で3つ、複勝で5つもフィールドが用意されているのは、同着があり得るからですね。

さぁ、これを、上述のRaceUmaのSELECT文に組み込むことが必要なのですが、いったいどうすればいいのでしょうか?本日のメインは、この、テーブルの結合を行う命令です。

RaceUmaとRaceを結合するには、以前に出てきたRaceIdという共通するフィールドを指定して結合するのが普通です。INNER JOIN という結合をまずは覚えましょう。

(テーブルA) INNER JOIN (テーブルB) ON (テーブルAのフィールド) = (テーブルBのフィールド) [and ・・・]

という感じで、ON以下に、結合のための条件を書きます。結合の条件は、andでつなげて、いくつも書けます。ふつうは等号(=)ですが、>とか>=なんかでもいけるはずです。

例えば、RaceUma(各出走馬の情報)に、Race(距離とかトラックとかのレース自体の情報)を付加して表示したい場合は、
「SELECT Race.競馬場名,Race.レース番号,RaceUma.馬番,RaceUma.馬名,RaceUma.確定着順 FROM (RaceUma INNER JOIN Race on RaceUma.RaceId = Race.RaceId)」 という感じです。

RaceUMAには、馬ごとのデータが入っていますので、そのレースの出走頭数分のデータが入っています。INNER JOINでRaceのテーブルを結合すると、RaceIDが同じものには、(イメージとしては複製をして)すべてくっつけます。おんなじ情報(レースの情報)を馬の数だけくっつけるわけなので、Raceテーブルのデータの量が、出走した馬の数字をかけた数増えるわけですね。

さて、では単勝の回収率を出すにはどうすればいいんでしょうか。
ある条件(例えば最終コーナー先頭とか)での回収率は、ある条件での出走馬を全部抽出して配当の平均を出すことで計算できます。

抽出するSQLは、

「SELECT RaceUma.馬番,RaceUma.馬名,RaceUma.確定着順,Race.単勝馬番1,Race.単勝払戻金1 FROM (RaceUma INNER JOIN Race on RaceUma.RaceId = Race.RaceId)」

このSQLで、全部の馬を抽出したら、単勝馬の馬番や単勝配当の額が全馬のデータの後ろにひっついています。

ここで、集計の為に、IIF という構文を使います。
これは、もし・・・だったら、この数字をそうでなければこの数字を・・・というふうに、条件に従って変換してくれる命令です。

Race.単勝馬番1と、RaceUma.馬番が一緒だったら、Raceテーブルの「単勝払戻金1」の値を、そうでなければ、0を入れれば、単勝配当のある馬は単勝配当の額が、そうでない馬は0が、という疑似的なフィールドに変換ができますね。命令作ると次のようになります。

「IIF(Race.単勝馬番1=RaceUma.馬番,Race.単勝払戻金1,0)」

SELECT文に組み込むと、

「SELECT Race.競馬場名,Race.レース番号,RaceUma.馬番,RaceUma.馬名,RaceUma.確定着順,IIF(Race.単勝馬番1=RaceUma.馬番,Race.単勝払戻金1,0) FROM (RaceUma INNER JOIN Race on RaceUma.RaceId = Race.RaceId)」

となります。

では、今度は集計をします。説明を単純にするために同着は考えません。条件等も指定せず、全レースの1着になった馬(正確に言うと、Raceテーブルの「単勝馬番1」フィールドに記載のある馬)の回収率を出します。単勝配当の合計を出して、総数で割ればいいですね。小数点1位までの表示にするために10を掛けて、整数表示にして、10で割りましょう。

「SELECT INT(SUM(IIF(Race.単勝馬番1=RaceUma.馬番,Race.単勝払戻金1,0))/count(*) *10)/10 FROM (RaceUma INNER JOIN Race on RaceUma.RaceId = Race.RaceId)」

さて、それでは、今度は、すでに作ってある、勝率を出すSELECT文に、上の回収率を表示するSQLを組み込んでみましょう。

「SELECT [対象のフィールド名] AS 区分,count(*) AS n, count(RaceUma.確定着順 =1 or null) AS 勝数, int(count(RaceUma.確定着順 =1 or null)/count(*)*1000)/10 AS 勝率,INT(SUM(IIF(Race.単勝馬番1=RaceUma.馬番,Race.単勝払戻金1,0))/count(*) *10)/10 AS 単勝回収率 FROM (RaceUma INNER JOIN Race on RaceUma.RaceId = Race.RaceId) GROUP BY [対象のフィールド名] 」

長ったらしいですが、これで勝率と単勝回収率いずれも出るはずです。

テストとして、下のSQLをクエリに打ち込んで、最終コーナーの順位別の単勝回収率を、調べてみましょう。最終コーナーの順位は、RaceUmaテーブルの、「コ4」というフィールドになります。

「SELECT RaceUma.コ4 AS 区分,count(*) AS n, count(RaceUma.確定着順 =1 or null) AS 勝数, int(count(RaceUma.確定着順 =1 or null)/count(*)*1000)/10 AS 勝率,INT(SUM(IIF(Race.単勝馬番1=RaceUma.馬番,Race.単勝払戻金1,0))/count(*) *1000)/10 AS 単勝回収率 FROM (RaceUma INNER JOIN Race on RaceUma.RaceId = Race.RaceId) GROUP BY RaceUma.コ4 」

動きました。結果が画像です。過去10年分くらいのデータですが、最終コーナーで先頭の馬は単勝回収率がいいですね。

本日はここまで。次回以降で、同着の処理や、競走除外、発走除外等の修正、複勝回収率の組み込みなどをしていきたいと思います。

関連キーワード

この日記へのコメント

コメントはありません。

新着競馬日記

人気競馬日記