• ベストアンサー

二つの配列を一つにまとめる(sqlでいうjoin)

データベースから別々に取得したデータを一つにまとめる方法で、 今やってるのはなんだか冗長な感じでいけてない気がするのですが、 ほかの方法が思いつかないので投稿いたしました。 $artist と $music に music_id というカラムがあって、これが一致するものだけを取得する。 以下今やってる方法。 foreach ($artist as $key => $value) { $flg = false; foreach ($music as $k => $v) { if($value["music_id"] == $v["music_id"]) { $flg = true; break; } if ($flg) { $data[] = $value; } } } やっぱりなんだかいけてないですねーorz いい方法を教えてください!

質問者が選んだベストアンサー

  • ベストアンサー
  • shimix
  • ベストアンサー率54% (865/1590)
回答No.4

ANo.1です。 失礼、配列の並びを読み間違えてましたね。一度配列のキーを入れ替えるという処理をいれたらどうでしょう?   foreach ($music as $value) {     $warr[$value['music_id']] = $value['category_id'];     } そうしておけば楽に扱えると思います。   foreach ($artist as $value) {     $key = $value['music_id'];     if (array_key_exists($key, $warr)) {        print $key . ":" . $value['artist_id'] . "/" . $warr[$key] . "<br />";       }     } ソースの華麗さはともかくforeachの2重Loopは処理のオーダーを考えるとしたくないと思うので(データが多ければ多いほど・・ですね)。

kamui-h
質問者

お礼

ありがとうございます!! >ソースの華麗さはともかくforeachの2重Loopは処理のオーダーを考えるとしたくないと思うので(データが多ければ多いほど・・ですね)。 そうなんですよね・・・。 一応このように作った場所もあるんですが、分けると見づらいと思って 大部分は最初に書いたように2重Loopにしちゃってるんですよ。 でも、それはそれで結局見づらいというダメダメLoop・・・。

その他の回答 (5)

  • little-m
  • ベストアンサー率44% (45/102)
回答No.6

以下のロジックはいかがでしょうか? $chk = array(); foreach ($music as $v) { $k = $v['music_id']; $chk[$k] = $k; } foreach ($artist as $v) { $k = $v['artist_id']; if (isset($chk[$k])) { $data[] = $v; } } ただしこれは一般的な「突合せ処理」のロジックに比べて処理効率が良いかはわかりません。(レコードが多ければ突合せの方が良いと思います) (突合せ処理) 1)$artist を artist_id でソート 2)$music を music_id でソート 3)$artist と $music を突合せでループ(それぞれのidの小さい方のポインタを順に次へ移して行き、入れ子のループにしないロジック) ※突合せ処理は、プログラムロジックの結構基本なので、ネット上のどこかに載っていると思いますが、今すぐにURLがわかりませんでした。(サンプルソースを自分で記載するのは面倒でした。すみません)

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.5

ANo.4です。蛇足ですが(汗 DBから取得して配列に入れる時点で、artistテーブルならartist_id、musicテーブルならmusic_idをキーにしませんかね?私はそうしておくことが多いので「array_key_exists一発では?」と思ってしまったので(汗

kamui-h
質問者

補足

蛇足ありがとうございます(>< 基本的に上の人が作成したものを(PEARをラップして作ってる)使うような形なのでそのあたりはつつけないのです・・・。っというか、考えたこともなかったですw なるほど、どうせユニークなんだから有効活用しなくちゃいけませんね。 勉強になりました!ありがとうございます!!

  • tols
  • ベストアンサー率46% (7/15)
回答No.3

なるほど。 いろいろなクライアントさんが居るんですね。 ひとつ勉強になりました。ありがとうございます!! (何か私が質問者みたいですね・・・w) 老婆心ながら、以下のようにソースを手直ししてみました。 foreach ( $artist as $key => $value ) {   foreach ( $music as $k => $v ) {     // 型までチェックに含めると良いかと思います。     if( $value["music_id"] !== $v["music_id"] ) {      continue;     }     // ifステートメントに書くと、わかりにくいので、私はこういう風に書いています。     $data[] = $value;   } }

kamui-h
質問者

お礼

DBが落ちないようにということらしいです。 大量のアクセスを見込んでるのでしょうw サンプルソースありがとうございます! 自分のよりもシンプルでわかりやすいです!!

  • tols
  • ベストアンサー率46% (7/15)
回答No.2

上記処理を行う理由をもし可能であれば教えて頂ければ幸いです。 ご存知かと思いますが、下記SQL文でも条件に当てはまる結果は得られます。 SELECT a.* FROM artist as a, music as m WHERE a.music_id = m.music_id LIMIT 0, 30;

kamui-h
質問者

お礼

回答ありがとうございます。 理由はいろいろあるのですが、 DBに負担をかけないように(joinとかinとかあんまり使うなと・・・)細かく切り出して、 できるだけPHP側で処理してほしいという要望があったりするのです。 あとはDB同士に限らず、ほかの場合にもこういったことがあったので PHPで処理する場合になにがベストなのか知りたかったのです。

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.1

phpのバージョンがわかりませんが、php5以降なら   http://www.php.net/manual/ja/function.array-intersect-key.php を使うのが楽だと思います。php4なら外側のforeachは仕方ないにしても、内側はforeachで回さずに   http://www.php.net/manual/ja/function.array-key-exists.php でチェックすればいいのではないでしょうか? #「データベースから取り出す時点で工夫しておく」のが最善だと思いますけど

kamui-h
質問者

お礼

回答ありがとうございます。 データベースから取得した値は以下と同じように変数に格納されますよね。 artistテーブルのデータ $artist = array( array( 'artist_id' => 1, 'music_id' => 100, ), array( 'artist_id' => 2, 'music_id' => 100, ), array( 'artist_id' => 3, 'music_id' => 100, ), array( 'artist_id' => 4, 'music_id' => 100, ), array( 'artist_id' => 5, 'music_id' => 1, ), ); musicテーブルのデータ $music = array( array( 'music_id' => 1, 'category_id' => 1, ), array( 'music_id' => 2, 'category_id' => 1, ), array( 'music_id' => 3, 'category_id' => 1, ), array( 'music_id' => 100, 'category_id' => 1, ), ); で、この関数では配列のキーが同じなら取得するようなので 0~3までの配列は全て取得されて、 期待した値は取得できないのではないでしょうか。 (やり方が悪いのですかね・・・) キーが同じなのはもちろんですが、値も同じものを取得したいのです。 できればサンプルコードを載せてもらえるとありがたいです。 array-key-exists もどう使うのかわかりません・・・。すみません。

関連するQ&A