白駒牧場さまの記事について。血統表の表示ロジック、作る前は難しそうで二の足を踏んでいたのですが、作ってみたらそれほど難しくなかったというのが実感です。
1.データの持ち方
データは以下のように何の工夫もなく持っています。テーブルを設計した時点では、血統表を作るかどうか決めかねていたので、血統表を意識せずにテーブルを設計しました。ですので、このデータの持ち方では苦労するのではないかと予想していました。基本的にはperlで作る場合でも、ファイルシステムを使う場合でもデータの持ち方はこれでいいと思います。
| 現役馬テーブル | 繁殖馬テーブル | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
2.データの取り方
・現役馬「001」(ディープインパクト)のページをリクエスト
・現役馬「001」の父「100」をキーにして、繁殖馬テーブルを検索し、父父「101」と、父母「201」を取得する。
・父父「101」をキーにして繁殖馬テーブルを検索し、父父父「103」と、父父母「203」を取得する。
・父父父「103」をキーにして・・・・
・父父母「203」をキーにして・・・・
・現役馬001の母「200」をキーにして、繁殖馬テーブルを検索し、父父「102」と、父母「202」をを取得する。
・全部取得したらテーブルに配置。取得できなかったら「−」。
こんな感じです。繁殖テーブルを検索ところを関数にしておけば使いまわせるので、そんなに面倒ではありません。
ソースなんぞお見せしてもつまらないとは思いますが、こんな感じになってます。
//血統表表示する関数
function blood_table($sire_in, $dam_in){
global $PHP_SELF;//データの取得 decode_sireは繁殖馬コードをキーにして、繁殖馬のデータ(名前、生年等)を取得する自作の関数
$decode_blood3 = decode_sire($sire_in["SIRE"], "sire");
$decode_blood4 = decode_sire($sire_in["DAM"], "dam");
$decode_blood5 = decode_sire($dam_in["SIRE"], "sire");
$decode_blood6 = decode_sire($dam_in["DAM"], "dam");
$decode_blood7 = decode_sire($decode_blood3["SIRE"], "sire");
$decode_blood8 = decode_sire($decode_blood3["DAM"], "dam");
$decode_blood9 = decode_sire($decode_blood4["SIRE"], "sire");
$decode_blood10 = decode_sire($decode_blood4["DAM"], "dam");
$decode_blood11 = decode_sire($decode_blood5["SIRE"], "sire");
$decode_blood12 = decode_sire($decode_blood5["DAM"], "dam");
$decode_blood13 = decode_sire($decode_blood6["SIRE"], "sire");
$decode_blood14 = decode_sire($decode_blood6["DAM"], "dam");
$decode_blood15 = decode_sire($decode_blood7["SIRE"], "sire");
$decode_blood16 = decode_sire($decode_blood7["DAM"], "dam");
$decode_blood17 = decode_sire($decode_blood8["SIRE"], "sire");
$decode_blood18 = decode_sire($decode_blood8["DAM"], "dam");
$decode_blood19 = decode_sire($decode_blood9["SIRE"], "sire");
$decode_blood20 = decode_sire($decode_blood9["DAM"], "dam");
$decode_blood21 = decode_sire($decode_blood10["SIRE"], "sire");
$decode_blood22 = decode_sire($decode_blood10["DAM"], "dam");
$decode_blood23 = decode_sire($decode_blood11["SIRE"], "sire");
$decode_blood24 = decode_sire($decode_blood11["DAM"], "dam");
$decode_blood25 = decode_sire($decode_blood12["SIRE"], "sire");
$decode_blood26 = decode_sire($decode_blood12["DAM"], "dam");
$decode_blood27 = decode_sire($decode_blood13["SIRE"], "sire");
$decode_blood28 = decode_sire($decode_blood13["DAM"], "dam");
$decode_blood29 = decode_sire($decode_blood14["SIRE"], "sire");
$decode_blood30 = decode_sire($decode_blood14["DAM"], "dam");//リンクの生成 blood_listは上で得た繁殖馬コードをキーにして、繁殖馬のデータへのリンクタグを生成する自作の関数
$blood1 = blood_list($sire_in);
$blood2 = blood_list($dam_in);
$blood3 = blood_list($decode_blood3);
$blood4 = blood_list($decode_blood4);
$blood5 = blood_list($decode_blood5);
$blood6 = blood_list($decode_blood6);
$blood7 = blood_list($decode_blood7);
$blood8 = blood_list($decode_blood8);
$blood9 = blood_list($decode_blood9);
$blood10 = blood_list($decode_blood10);
$blood11 = blood_list($decode_blood11);
$blood12 = blood_list($decode_blood12);
$blood13 = blood_list($decode_blood13);
$blood14 = blood_list($decode_blood14);
$blood15 = blood_list($decode_blood15);
$blood16 = blood_list($decode_blood16);
$blood17 = blood_list($decode_blood17);
$blood18 = blood_list($decode_blood18);
$blood19 = blood_list($decode_blood19);
$blood20 = blood_list($decode_blood20);
$blood21 = blood_list($decode_blood21);
$blood22 = blood_list($decode_blood22);
$blood23 = blood_list($decode_blood23);
$blood24 = blood_list($decode_blood24);
$blood25 = blood_list($decode_blood25);
$blood26 = blood_list($decode_blood26);
$blood27 = blood_list($decode_blood27);
$blood28 = blood_list($decode_blood28);
$blood29 = blood_list($decode_blood29);
$blood30 = blood_list($decode_blood30);//表示
print "
<table class=\"regist\" >
<tr>
<td rowspan=\"16\" class=\"sire\" >{$blood1}</td>
<td rowspan=\"8\" class=\"sire\" >{$blood3}</td>
<td rowspan=\"4\" class=\"sire\" >{$blood7}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood15}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood16}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"4\" class=\"dam\" >{$blood8}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood17}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood18}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"8\" class=\"dam\" >{$blood4}</td>
<td rowspan=\"4\" class=\"sire\" >{$blood9}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood19}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood20}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"4\" class=\"dam\" >{$blood10}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood21}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood22}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"16\" class=\"dam\" >{$blood2}</td>
<td rowspan=\"8\" class=\"sire\" >{$blood5}</td>
<td rowspan=\"4\" class=\"sire\" >{$blood11}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood23}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood24}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"4\" class=\"dam\" >{$blood12}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood25}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood26}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"8\" class=\"dam\" >{$blood6}</td>
<td rowspan=\"4\" class=\"sire\" >{$blood13}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood27}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood28}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"4\" class=\"dam\" >{$blood14}</td>
<td rowspan=\"2\" class=\"sire\" >{$blood29}</td>
</tr>
<tr> </tr>
<tr>
<td rowspan=\"2\" class=\"dam\" >{$blood30}</td>
</tr>
<tr> </tr>
</table>
";
}
3.系統検索
むしろ難しいのは、逆の検索だと思います。 つまり、「系統検索」。
ある繁殖馬からその直仔を検索するところまではそれほど難しくはないのですが、上のデータの持ち方で「ノーザンダンサー系」、「ヘイロー系」などの系統を検索するのは難しいです。問題は以下の二つ。(1)何代先まで検索を繰り返せばいいのかがわからない、(2)大きなテーブル相手に大きな検索をかけるので、非常に重くなる。TARGETでも系統検索が可能になりましたが、「セントサイモン系」なんぞ検索しようものなら、えらい時間がかかります。
検索を軽くするためには検索を絞り込むためのデータを「繁殖テーブル」持つ必要があります。会計のシステムでも、「予算科目」、「勘定科目」の細目とかつける場合には、ツリー構造のデータのもち方をします(RDBでのデータの持ち方はややこしいので割愛)。
階層構造をもったデータの管理に適してるのがXMLDBだと認識していますので、基本的には血統データの管理には向いてるとは思います。
4.XMLDB
ただ・・・。
お勉強がてらXMLでDBを構築することも一瞬頭をよぎりましたが、やめました。データの作成・更新はまだいいにしても(といってもデータ設計のイメージは湧いてない)、データ検索・表示のところを作るのが大変そうなのと、パフォーマンスチューニングに至っては見当もつかなかったのが理由です(=スキルがない)。セキュリティも少し心配でした。まぁ、いったんMySQLでデータを持ってしまった以上、同じデータをXMLで持つのは正規化の観点から合理的ではないので、XML化をする予定は当面ありません。まだまだバグもありますし(笑)。しかし・・・・。
XMLDBでの開発にはなかなか踏み切れないのはなぜだろうか。これには、XMLのツリー構造でデータを定義した経験がなく、なんとなく覚えるのが大変そうだといった、いわゆる「食わず嫌い」が大きく影響しているようだ。これなら簡単 RDBからXMLDBへのデータ移行より
これはあたりw まさに「なんとなく大変そう」。効率性の高いデータの持ち方を考えるのにはとても頭を使います。その点、RDB&SQLは慣れてしまえば頭使わないでいいんですよね・・。
5.UMASQL
あれは基本的にJRA-VANのデータをRDBMSにぶち込んでるんだと思います。血統表の穴がある部分が同じですし、カバーしてる期間も同じなので。整形されたデータを処理すればいいだけなので、一回インターフェースとってしまえばわりと管理は楽なんじゃないかなと思います・・・。大量のアクセスに対応するのが大変でしょうけれど。
6.セッション
senchouさま@四号館ご紹介のdev.ishinao.netさまの記事の中では、セッションを使ってみたいと思いました。現在のところセキュリティを全然考えていないので、ろくな入力画面をつくれていないのです。
ほとんど参考にはならないと思いますが、こんな感じです。それにしても自分の書いたヘボソースを出すのは恥ずかしいな・・。