重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

データベースに親子関係が書かれていて、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] をデータベースから読み出すのでしょうか?

データベースアクセスは配列アクセスと比べて桁違いに重い処理の気がするので、
もっと賢い記載方法がある気がしています。

質問者からの補足コメント

  • HAPPY

    データベースに、 階層の深さと、関連要素の範囲を示すデータを追加することで、

    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

      補足日時:2020/04/03 10:37

A 回答 (7件)

MySQLのバージョン8からは、再帰クエリが書けるようになったので、一発で取得できるSQLも書けるのですが。


例)
https://oraclesqlpuzzle.ninja-web.net/mysql/code …


方針1: PHPにデータベースの情報を全部取り込んで、Cと同じようなやり方で処理する
方針2: 方針1の方法をMySQLのストアドプロシージャで実現する。
方針2': 1IDずつ検索してたら時間がかかるので、JOINを使って一気に処理する。
 結果を別テーブルにでも保存しておいて、普段はそちらを参照する

というあたりが現実的なやりかたではないでしょうか。
    • good
    • 0
この回答へのお礼

回答ありがとうございます

3種類の方針ありがとうございます。

方針2が魅力的ですが、親をたどる処理をストアドプロシージャで実現できるということでしょうか?
つまり、MySQLへの問い合わせは一発で、
 哺乳類- サル目(霊長類)- ヒト科 - チンパンジー属
が帰ってくるストアドプロシージャが書けるということでしょうか?

再帰クエリは知りませんでしたが、一発で取得できるなら魅力的ですが、バージョン8以降というのが難点ですね。

お礼日時:2020/03/31 21:01

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);
}
    • good
    • 0
この回答へのお礼

>富豪的
増井氏のあれですね。

実用性では、おっしゃるとおりと思います。
参考にさせていただきます。

お礼日時:2020/03/31 20:42

# 関係データベースから必要な情報をすべて読み取る


$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));
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

># 関係データベースから必要な情報をすべて読み取る
確かに!!
でもそのためにはチンパンジーから哺乳類を得るまでに、

チンパンジー属 → ヒト科
ヒト科 → サル目(霊長類)
サル目(霊長類)→哺乳類

を検索する必要がありそうな気がしますが、そのあたりはどうするのでしょう?

お礼日時:2020/03/31 15:20

>>select name,mother from DB where id=i;


ではなく、出力に関連したデータを一括してDBから取得する方法があるのかと思ったものですが・・・

ありません。

>>データベースアクセスは配列アクセスと比べて桁違いに重い処理の気がするので、
もっと賢い記載方法がある気がしています。

たしかに桁違いに重いですね。
ですので、例えばMqSQLのデータベースを全てラムディスクとか、今ならばHDDではなく、SSDに作れば、ずっと早く処理できるようになると思います。
    • good
    • 0
この回答へのお礼

明確な回答ありがとうございます
>ありません。

これでC言語型のプログラミングしても馬鹿にさせずに済みますね。
安心しました。

お礼日時:2020/03/31 14:57

PHPというよりはRDBで木構造で管理すればよいですよ

    • good
    • 0
この回答へのお礼

回答ありがとうございます。
今回はMYSQL + PHP という枠組み内での解決策を検討していますので、ご回答、参考にさせていただきます。

お礼日時:2020/03/31 13:21

質問者さんは勘違いしています。


C言語の処理は、データベースに対する処理ではなく、メモリーに対する処理です。

この手の処理は、データベース側で親子関係が分かるようなカラムやキーを用意し、リレーション設定しておいて、それらを使って、親子をたどるような処理を行います。
ですから、データベースであるMySQLを使うなら、C言語もPHPも似たような処理方法となります。

ただ、C#のデータベース用フレームワークであるEntityFrameworkでは、そういうリレーションを作るSQLなどを自動生成して、データベースを生成してくれたりします。
似たようなことは、他の言語のフレームワークでもやってくれるかもしれません。
    • good
    • 0
この回答へのお礼

回答ありがとうございます

>質問者さんは勘違いしています。
すいません、せっかくのご回答、理解できません。もう少しかみ砕いて回答いただけますか?

MySQLでは、C言語もPHPも似たような処理方法となり、もっと賢い記載方法はない

ということですか?

 select name,mother from DB where id=i;

ではなく、出力に関連したデータを一括してDBから取得する方法があるのかと思ったものですが・・・

お礼日時:2020/03/31 13:18

問題解決へのアプローチを変えた方がいい。



まずC言語の処理を日本語に置き換えて、それをphpで置き換えてはどうか?

結局のところ、配列とループの処理なだけなんで。

これができたら次はSQLを勉強。
テーブル結合を勉強すれば、もっと簡単に解決。

頑張って。
    • good
    • 0
この回答へのお礼

回答ありがとうございます

>テーブル結合を勉強すれば、もっと簡単に解決。
ここの部分をもう少し具体的にアドバイスいただけたらと思います。

お礼日時:2020/03/31 13:13

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!