
データベースに親子関係が書かれていて、id番号を与えるとその祖先からのリストを表示するプログラムを考えています。
例えばチンパンジーに該当するid番号を与えると
哺乳類- サル目(霊長類)- ヒト科 - チンパンジー属
と表示するプログラムです
C言語ならば、
データベースは id番号に該当する名前char* name[id]、親 int mather[id]があるとして
char *str;
int i;
i= id;
str = name[i];
while(mather[i] != 0) {
i = mother[i];
str = name[i] + str; // 前に親の名前を追加する。実際は関数で実現
}
感じで書けますが、これをPHPので書くとどう書けばよいのか教えてほしいです。
C言語ではデータベースはnemeとmatherの配列で表していますが、PHPではMySQLから
select name,mother from DB where id=i;
で毎回name[i]とmother[i] をデータベースから読み出すのでしょうか?
データベースアクセスは配列アクセスと比べて桁違いに重い処理の気がするので、
もっと賢い記載方法がある気がしています。
No.7ベストアンサー
- 回答日時:
MySQLのバージョン8からは、再帰クエリが書けるようになったので、一発で取得できるSQLも書けるのですが。
例)
https://oraclesqlpuzzle.ninja-web.net/mysql/code …
方針1: PHPにデータベースの情報を全部取り込んで、Cと同じようなやり方で処理する
方針2: 方針1の方法をMySQLのストアドプロシージャで実現する。
方針2': 1IDずつ検索してたら時間がかかるので、JOINを使って一気に処理する。
結果を別テーブルにでも保存しておいて、普段はそちらを参照する
というあたりが現実的なやりかたではないでしょうか。
回答ありがとうございます
3種類の方針ありがとうございます。
方針2が魅力的ですが、親をたどる処理をストアドプロシージャで実現できるということでしょうか?
つまり、MySQLへの問い合わせは一発で、
哺乳類- サル目(霊長類)- ヒト科 - チンパンジー属
が帰ってくるストアドプロシージャが書けるということでしょうか?
再帰クエリは知りませんでしたが、一発で取得できるなら魅力的ですが、バージョン8以降というのが難点ですね。
No.6
- 回答日時:
No.5 のお礼に対して
情報の総数が、高々数万であれば、
何も考えずに全部取ってしまいましょう。
これは富豪的と呼ばれる手法で、昨今の贅沢な環境ならば何ら問題ありません。
総数が大量または不明、または実行環境が低性能である前提ならば、
繰り返しの度に関係データベースへ問い合わせしましょう。
少々保守的な考えですが、処理効率よりも安全性のほうが重要です。
効率よく安全に処理したいという要件があるならば、
以下のようなキャッシュ機構の導入を検討してください。
https://www.php.net/manual/ja/intro.memcached.php
遅いデータベース処理結果をキャッシュすることで、必要な情報が効率的に使用できます。
$m = new Memcached();
$m->addServer( ... );
$classification = $m->get('mammal');
if (empty($classification)) {
$classification = データベース問い合わせ("哺乳類の分類全部");
$m->set('mammal', $classification);
}
No.5
- 回答日時:
# 関係データベースから必要な情報をすべて読み取る
$mysqli = new mysqli( ... );
$result = $mysqli->query("SELECT id,name,mother FROM 分類 WHERE 哺乳類限定の条件");
$classification = [];
while ($r = $result->fetch_assoc()) {
$i = $r['id'];
$classification[$i] = $r;
}
# 読み取った情報だけで編集する
$names = [];
$i = チンパンジーのid番号;
while (array_key_exists($i, $classification)) {
$c = $classification[$i];
$names[] = $c['name'];
$i = $c['mother'];
}
$name = implode(' - ', array_reverse($names));
回答ありがとうございます。
># 関係データベースから必要な情報をすべて読み取る
確かに!!
でもそのためにはチンパンジーから哺乳類を得るまでに、
チンパンジー属 → ヒト科
ヒト科 → サル目(霊長類)
サル目(霊長類)→哺乳類
を検索する必要がありそうな気がしますが、そのあたりはどうするのでしょう?
No.4
- 回答日時:
>>select name,mother from DB where id=i;
ではなく、出力に関連したデータを一括してDBから取得する方法があるのかと思ったものですが・・・
ありません。
>>データベースアクセスは配列アクセスと比べて桁違いに重い処理の気がするので、
もっと賢い記載方法がある気がしています。
たしかに桁違いに重いですね。
ですので、例えばMqSQLのデータベースを全てラムディスクとか、今ならばHDDではなく、SSDに作れば、ずっと早く処理できるようになると思います。
No.2
- 回答日時:
質問者さんは勘違いしています。
C言語の処理は、データベースに対する処理ではなく、メモリーに対する処理です。
この手の処理は、データベース側で親子関係が分かるようなカラムやキーを用意し、リレーション設定しておいて、それらを使って、親子をたどるような処理を行います。
ですから、データベースであるMySQLを使うなら、C言語もPHPも似たような処理方法となります。
ただ、C#のデータベース用フレームワークであるEntityFrameworkでは、そういうリレーションを作るSQLなどを自動生成して、データベースを生成してくれたりします。
似たようなことは、他の言語のフレームワークでもやってくれるかもしれません。
回答ありがとうございます
>質問者さんは勘違いしています。
すいません、せっかくのご回答、理解できません。もう少しかみ砕いて回答いただけますか?
MySQLでは、C言語もPHPも似たような処理方法となり、もっと賢い記載方法はない
ということですか?
select name,mother from DB where id=i;
ではなく、出力に関連したデータを一括してDBから取得する方法があるのかと思ったものですが・・・
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
JSTLを利用してJavascriptの結...
-
ASP.NET(VB)VBソースからJavas...
-
ブラウザ閉じたらサーバー処理...
-
jsonテキストデータの並び替え...
-
queryselctorのセレクタの後ろ...
-
JSONのコメント行の書き方...
-
インターネット上のファイルサ...
-
jQuery.getでレスポンスデータ...
-
非道式6進カウンタと非同期式10...
-
テキストファイルの内容を変数...
-
csvを使用したデータバインド(...
-
【JavaScript】confirmのボタン...
-
DirectXとOpenGLはどちらが動作...
-
リンクを押すとEXEファイルを実...
-
saved from url=(0013)abou
-
アップロードするとレイアウト...
-
ローカルファイル(mp3)の再生
-
jQueryの$.postの戻り値による...
-
ジャンクの箇所を一切書かずに...
-
ローカルでのhtmlチェックにつ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
sleepの負荷
-
呼び出し元のURLを知りたいのです
-
ASP.NET(VB)VBソースからJavas...
-
ブラウザを閉じた瞬間にログアウト
-
PHPでフォームの自動入力できま...
-
GDとImageMagick どっちがおす...
-
php ob_flushが全く動作しない
-
このプログラムの認証ウィンド...
-
掲示板の作り方
-
イベント処理について
-
自作PHPがどれ程サーバの負担に...
-
読み込み中に「Now Loading」を...
-
スクリプト言語でおすすめのもの
-
PHPを書籍で勉強しているのですが
-
PHP内でJavaScriptの処理は可能?
-
PHPでオンライン将棋ゲーム
-
mkdirでフォルダ名“予定表示”を...
-
PHPを用いてPOSTし、リダイレク...
-
jQueryのAjaxで通信の途中結果...
-
10秒毎に同じプログラムを繰り...
おすすめ情報
データベースに、 階層の深さと、関連要素の範囲を示すデータを追加することで、
select group_concat(name order by level desc separator '-') as names from animal as t1
where exists(select 1 from animal where id=50001 and l between t1.l and t1.r)
のような1回のデータベースからの読み出しで、
哺乳類- サル目(霊長類)- ヒト科 - チンパンジー属
が得られる方法、別の質問で解決しました。
https://oshiete.goo.ne.jp/qa/11557860.html