• ベストアンサー

for文の組み合わせ方

PHPで以下のTableからデータを取ってきて 取り扱い表を作成したいと思っています。 Table:SHOPは店舗、Table:ITEMは商品、Table:LINKは 先の二つの紐付けを表します。 DBの保存データは、 Table:SHOP ID  SHOPNAME ------------------- 1   東京 2   大阪 3   福岡 (略) Table:ITEM ID ITEMNAME -------------------- 1  化粧品 2  家具 3  園芸 4  食品 5  家電 (略) Table:LINK ID  SHOP  ITEM --------------------- 1   1    4 2   2    5 3   3    1 4   3    2 (略) となっていて、結果として画面に   |化粧品|家具|園芸|食品|家電| ---------------------------------------- 東京|   |   |   | ○ |   | 大阪|   |   |   |   | ○ | 福岡| ○ | ○ |   |   |   | (略) と表示したいのですが、 $sql="SELECT A.ID,B.SHOPNAME,C.ITEMNAME FROM ・・・・・ としたのでは紐付けを単純に抽出するだけですし、 for文をどう使えば縦列に項目をだして○をつければ いいかがわかりません。 HELPお願いします。

  • PHP
  • 回答数3
  • ありがとう数3

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

  • ベストアンサー
  • hakugen
  • ベストアンサー率36% (8/22)
回答No.2

DBは何を使われているのでしょうか?外部結合で取って来ればそのような形になると思います。 また、Oracleであれば「DECODE」や「CASE」、MySQLであれば「IF」を用いればSQLで「○」も表現できます。(他のDBにもきっと似たようなものがあるのでは。) とりあえず商品だけは先にとっておく。 「SELECT ITEMNAME FROM ITEM ORDER BY ID」 そのあとに結果に表示したい形式で抽出。 「SELECT SHOPID,SHOPNAME,ITEMNAME, IF(L.ITEM=A.ITEMID,'○','') FROM (SELECT I.ID AS ITEMID,S.ID AS SHOPID, SHOPNAME,ITEMNAME FROM ITEM I, SHOP S) A LEFT OUTER JOIN LINK L ON L.ITEM = A.ITEMID AND A.SHOPID = L.SHOP ORDER BY SHOPID,ITEMID」 ちょっと複雑になってしまいましたが、これであとは結果をfor文で回していって、「SHOPID」が変わったら改行すればOKです。

getamato
質問者

お礼

お礼での書き込みになりますが、 追加質問なのですが、 >LEFT OUTER JOIN LINK L >ON L.ITEM = A.ITEMID の時に、LINK LのTableに非表示のフラグがあった 場合で、DELETE=0 という条件を付けたい場合どうしたらいいでしょうか。

getamato
質問者

補足

ありがとうございます。 DBはMySQLを使用しています。 IF、forでの回し方、使い方についてもHELPいただけましたら幸いです。 よろしくお願いします。

その他の回答 (2)

  • hakugen
  • ベストアンサー率36% (8/22)
回答No.3

> の時に、LINK LのTableに非表示のフラグがあった > 場合で、DELETE=0 という条件を付けたい場合どうしたらいいでしょうか。 ORDER句の前に入れれば良いかと。 「・・・・・・ AND A.SHOPID = L.SHOP WHERE DELETE = 0 ORDER BY SHOPID,ITEMID」 とりあえず出力だけを考えるなら・・・。 <?php $sql="ここにSQL文"; $result = mysql_query($sql,$con); $output = array(); //結果を格納する配列 while ($row = mysql_fetch($result)) { if($output["SHOPNAME"] == NULL) $output["SHOPNAME"] = array(); array_push($output["SHOPNAME"], $row["ITEMNAME"]); } ?> <table> <?php foreach($output["SHOPNAME"] as $key => $shop){ echo "<tr><td>".$key."</td><td>|</td>"; foreach($shop as $item) echo "<td>".$item."</td><td>|</td>"; echo "</tr>"; } ?> </table> 見出しの部分に関しては#1さんと同じです。 ただ、MySQLだと5.0でないと副問い合わせが使えないのですが・・・。

getamato
質問者

お礼

ありがとうございます。 まだ消化しきれていないところあり、コメントに感謝です。 自分でもいろいろやってみて、それについて質問しますので またよろしくお願いします。

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.1

簡単そうで結構やっかいな質問ですね。 もっとも単純にやるには、 SHOPとITEMとLINKをそれぞれ別に呼び出して、 PHPで合体ささせる方法です。以下の通り。 <?PHP $link = mysql_connect('localhost', 'root', 'koeinet100'); mysql_select_db('test'); $sql="SELECT `ID`,`SHOPNAME` FROM `SHOP`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $SHOP[$rows["ID"]]=$rows["SHOPNAME"]; } $sql="SELECT `ID`,`ITEMNAME` FROM `ITEM`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $ITEM[$rows["ID"]]=$rows["ITEMNAME"]; } foreach($SHOP as $key1=>$val1){ foreach($ITEM as $key2=>$val2){ $LINK[$key1][$key2]="&nbsp;"; } } $sql="SELECT `SHOP`,`ITEM` FROM `LINK`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $LINK[$rows["SHOP"]][$rows["ITEM"]]="○"; } print<<<eof <table border> <thead> <tr> <th>&nbsp;</th> eof; foreach($ITEM as $key2=>$val2){ print "<th>$val2</th>"; } print<<<eof </tr> </thead> <tbody> eof; foreach($SHOP as $key1=>$val1){ print "<tr>"; print "<td>$val1</td>"; foreach($ITEM as $key2=>$val2){ print "<td>{$LINK[$key1][$key2]}</td>"; } print "</tr>"; } print<<<eof </tbody> </table> eof; ?> しかしこれではなんのためにSQLで管理しているか さっぱりわかりません。 そこで応用ですが、ピボットテーブルという 縦軸を横軸に転写するテーブルを作って処理します。 以下、SQL文だけ参考に。 #まずテンポラリでテーブル作成 CREATE TEMPORARY TABLE `TEMP_PIVOT`(`ID` INT,`化粧品` INT,`家具` INT,`園芸` INT,`食品` INT,`家電` INT); #左上から右下にたいして1が入るようにデータを挿入 INSERT INTO `TEMP_PIVOT` VALUES(1,1,0,0,0,0),(2,0,1,0,0,0),(3,0,0,1,0,0),(4,0,0,0,1,0),(5,0,0,0,0,1); #ピボットを使って抽出 SELECT `SHOP`.`ID`,`SHOPNAME` ,SUM(`化粧品`) AS `化粧品` ,SUM(`家具`) AS `家具` ,SUM(`園芸`) AS `園芸` ,SUM(`食品`) AS `食品` ,SUM(`家電`) AS `家電` FROM `SHOP` LEFT JOIN `LINK` ON `SHOP`.`ID`=`LINK`.`SHOP` LEFT JOIN `TEMP_PIVOT` ON `TEMP_PIVOT`.`ID`=`LINK`.`ITEM` GROUP BY `SHOPNAME` ORDER BY `SHOP`.`ID`;

getamato
質問者

補足

応用まで! ありがとうございます。 PHPで結合する方法から勉強していきたいと思うのですが、一点追加で質問させてください。 最終的にはこの画面表示をCSVなりに吐き出したいと思っています。 この場合はPHPでの結合だとどのようにすればいいでしょうか。 よろしくお願いします。

関連するQ&A

  • foreachの表示に追加するには

    http://okwave.jp/qa2460708.html と同じようなテーブル構造で、同じようなhtmlへの書き出しを行っています。 No.1さんの回答の下記のスクリプトを参考にし、うまく表示することができました。 $sql="SELECT `ID`,`SHOPNAME` FROM `SHOP`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $SHOP[$rows["ID"]]=$rows["SHOPNAME"]; } $sql="SELECT `ID`,`ITEMNAME` FROM `ITEM`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $ITEM[$rows["ID"]]=$rows["ITEMNAME"]; } foreach($SHOP as $key1=>$val1){ foreach($ITEM as $key2=>$val2){ $LINK[$key1][$key2]="&nbsp;"; } } $sql="SELECT `SHOP`,`ITEM` FROM `LINK`"; $res = mysql_query($sql,$link); while ($rows = mysql_fetch_assoc($res)) { $LINK[$rows["SHOP"]][$rows["ITEM"]]="○"; } print<<<eof <table border> <thead> <tr> <th>&nbsp;</th> eof; foreach($ITEM as $key2=>$val2){ print "<th>$val2</th>"; } print<<<eof </tr> </thead> <tbody> eof; foreach($SHOP as $key1=>$val1){ print "<tr>"; print "<td>$val1</td>"; foreach($ITEM as $key2=>$val2){ print "<td>{$LINK[$key1][$key2]}</td>"; } print "</tr>"; } print<<<eof </tbody> </table> eof; しかし、下記のテーブルに項目が1つ追加され、それも表示できるようにして欲しいと依頼されました。 Table:SHOP ID  SHOPNAME STATION ------------------------ 1   東京 | 表参道 2   大阪 | 梅田 3   福岡 | 天神 (略) 結果としては下記のように表示したいです。 NAME |STATION|化粧品|家具 |園芸 |食品 |家電 | ------------------------------------------------ 東京 | 表参道|   |   |   | ○ |   | 大阪 | 梅田 |   |   |   |   | ○ | 福岡 | 天神 | ○ | ○ |   |   |   | (略) 配列をよく理解できていないため、スクリプトをそのまま真似して $STATION[$rows["ID"]]=$rows["STATION"]; を作ったり $SHOP[$rows["ID"]][$rows["STATION"]]=$rows["SHOPNAME"]; を作ったりして無理矢理展開してみようとしましたが やはり表がぐちゃぐちゃになってしまいます。 どうすればうまく表示できるか、アドバイス頂けませんでしょうか。

    • ベストアンサー
    • PHP
  • for文の組み合わせ方 [2]

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=2460708 の関連質問になります。 最初に前回コメントいただけた方にお礼申し上げます。 前回お伺いした方法で、 $sql="SELECT ID,ITEMNAME FROM ITEM ORDER BY ID"; $msql="SELECT SHOPID,SHOPNAME,ITEMNAME,IF(L.ITEM=A.ITEMID,'○','') FROM (SELECT I.ID AS ITEMID,S.ID AS SHOPID,SHOPNAME,ITEMNAME FROM ITEM I, SHOP S) AS A LEFT OUTER JOIN LINK L ON L.ITEM = A.ITEMID AND A.SHOPID = L.SHOP ORDER BY SHOPID,ITEMID"; でデータを取得し、 下記で行列に店名と商品を表示する事ができました。 $in = mysql_query($sql,$db) $in2 = mysql_query($msql,$db) $ln = mysql_num_rows($in); $ln2 = mysql_num_rows($in2); print("<TABLE border=1>"); print("<TR>"); print("<TD>"); print("</TD>"); for($i=0;$i<$ln;$i++) { $lw = mysql_fetch_row($in); print("<TD>".$lw[1]."</TD>"); } print("</TR>"); print("<TR>"); for($i=0;$i<$ln2;$i++) { $lw2 = mysql_fetch_row($in2); print("<TD>".$lw2[1]."</TD>"); //○を付ける処理 //print("<TD>".$lw2[3]."</TD>"); print("</TR>"); } print("</TABLE>"); ただ「SHOPIDが変わったら改行」という処理方法がわからずの状態になっています。 IF文で○じゃなければ<TD></TD>を埋め込む?などと思いやってみましたが やり方がおかしいのかうまくいっていません。 値の比較方法と、それをどのように組み込めばいいかコメントお願いします。 ※併せてですが、この後このPHPで作成された表をCSVに出力したいのですが、可能でしょうか?

    • ベストアンサー
    • PHP
  • select文のWHERE句に関して

    SELECT文の質問になります。 店舗テーブルとメリットテーブルが存在し、それを紐付ける「店舗・メリット紐付けテーブル」が存在します。 店舗テーブル ・SHOP_ID  ・SHOP_NAME 特徴テーブル ・MERIT_ID ・MERIT_NAME 店舗・特徴紐付けテーブル ・SHOP_ID ・MERIT_ID 店舗・メリット紐付けテーブルの中身は以下になるとして SHOP_ID  MERIT_ID 1       1 1       2 2       2 2       3 3       1 3       2 1と2の「MERIT_ID」を"両方とも"保持している「SHOP_ID」を取得したいと思っております。 結果として、1と3の「SHOP_ID」を取得したいです。 どの用にすればよろしいでしょうか。 宜しくお願いします。

  • foreachの間にテーブルの<TR>を出力

    HTMLのテーブルにデータを入れたいのですが、 6列ごとに改行の<tr></tr>を入れる方法が分かりません。 下のように並べたいです [ITEMNAME][ITEMNAME][ITEMNAME][ITEMNAME][ITEMNAME][ITEMNAME] [ITEMNAME][ITEMNAME][ITEMNAME][ITEMNAME][ITEMNAME][ITEMNAME] データは1~12個きますので、一行の時と二行にわたる時、<td></td>に何もデータが入らない時もあります。 今現在このような感じです。 <table width="600"> <tr> <?php foreach ($item_array as $item){ ?> <td width="100" align="center"> <?=$str = mb_strimwidth($item['ITEMNAME'], 0, 100, "...");?> </td> <?php } ?> </tr> </table> どうか宜しくお願い致します。 既に他で同じ内容が出ていますが、そちらでは理解して応用できませんでしたので改めて質問させて頂きました。ごめんなさい。

    • ベストアンサー
    • PHP
  • COUNTについて

    今2つのテーブル(table1には商品IDと商品名、table2にはレシートIDと商品ID)を用い、 table1にある商品がtable2に何回登場しているかCOUNTを用いて数えたいのですが、 1回も登場しない商品が結果に表示されなくて困っています。 以下の様なテーブルを用いています。 [table1] 項目:item_id(主キー)|name 0|"item0" 1|"item1" 2|"item2" [table2] 項目:detail_id(主キー)|item_id(外部キー) 0|0 1|0 2|1 このとき、 SELECT table1.name,COUNT(*) FROM table1,table2 WHERE table1.item_id = table2.item_id GROUP BY table1.name; のようなSQL文だと、結果にitem2が含まれず、 item0とitem1の登場回数だけ表示されてしまいます。 これをitem2は0回登場していることがわかるように出力したいのですが、 どうしたらいいでしょうか。

    • ベストアンサー
    • MySQL
  • SQL文の抽出がうまくいきません。ご指導お願いいたします。

    写真を添付していない投稿も表示させたいのです。 今のSELECT文だと写真添付されているものだけ抽出されます。 tokou_table(略t) ┌───┬────┬────┐ |tku_id|cont_id |post_id | ├───┼────┼────┤ |001  | 5   |21   | ├───┼────┼────┤ |002  | 4   |22   | └───┴────┴────┘ post_table(略p) ┌───┬────┬────┐ |pst_id|cont_id |atch_id | ├───┼────┼────┤ |21 | 5 |0    | ├───┼────┼────┤ |22 | 4 |1 | └───┴────┴────┘ post_text_table(略pt) ┌───┬────┬────┐ |pst_id|pst_sub |pst_txt | ├───┼────┼────┤ |21 | 実験 |テキスト| ├───┼────┼────┤ |22 |サンプル|書込み | └───┴────┴────┘ atch_table(略at) ┌───┬────┐ |pst_id|atch_id | ├───┼────┤ |21 | 51 | └───┴────┘ atch_dat_table(略ad) ┌────┬────┐ |atch_id |pht_dat | ├────┼────┤ |51 |a.jpg | └────┴────┘ $sql = "SELECT t.tku_id, t.cont_id, p.forum_id, p.pst_id, pt.pst_id, pt.pst_txt, ad.atch_id, at.pst_id, at.atch_id, ad.pht_dat FROM " . TOKOU_TABLE . " AS t, " . POST_TABLE . " AS p, " . POST_TEXT_TABLE . " AS pt," . ATCH_TABLE . " AS at, " . ATCH_DAT_TABLE . " AS ad WHERE t.cont_id = 4 AND t.cont_id = p.cont_id AND p.pst_id = t.post_id AND p.pst_id = pt.pst_id AND pt.pst_id = at.pst_id AND at.atch_id = ad.atch_id

    • ベストアンサー
    • MySQL
  • SQL文の重複の削除でうまくいきません。

    昨日は回答いただきありがとうございました。 恐縮ですが、また質問させていただきます。 ひとつの投稿に対して2つの添付ファイルがある場合post_tableのtku_idが重複しているのですが、それに対してpost_idの小さい方を表示させたいのです。 post_tableのデータはpst_idで22と23がtku_idが同じで、22の方を表示させたいのです。 GROUP BY HAVING や自己リレーpost_table p2などやってみましたがダメでした。 どういうSQL文にするのがベストなんでしょうか? 未熟ものですが、ご指導いただけると助かります。 宜しくお願いいたします。 $sql = "SELECT t.tku_id, t.cont_id, p.pst_id, p.tku_id, pt.pst_id, pt.pst_txt, ad.atch_id, at.pst_id, at.atch_id, ad.pht_dat FROM " . TOKOU_TABLE . " AS t LEFT JOIN " . POST_TABLE . " p ON t.cont_id = p.cont_id LEFT JOIN " . POST_TEXT_TABLE . " pt ON p.pst_id = pt.pst_id LEFT JOIN " . ATCH_TABLE . " at ON at.pst_id = pt.pst_id LEFT JOIN " . ATCH_DAT_TABLE . " ad ON at.atch_id = ad.atch_id WHERE t.cont_id = 4 GROUP BY p.tku_id ORDER BY t.cont_id DESC "; tokou_table(略t)  tku_id cont_id  post_id     001   5    21   002   4    22 post_table(略p)  pst_id cont_id atch_id tku_id    21   5     0   001   22   4     1   002   23   4     1   002 post_text_table(略pt)  pst_id pst_sub pst_txt   21    実験  テキスト  22   サンプル 書込み atch_table(略at)  pst_id atch_id   21   51   23   52 atch_dat_table(略ad)  atch_id pht_dat    51   a.jpg   52   b.jpg MySQLは4.0.0-alph php4.2.3による記述です。

    • ベストアンサー
    • MySQL
  • SQL文作成についてお知恵をお貸しください

    ユーザーと商品のテーブル(省略)、 商品ジャンルテーブル、 genre id   name 1   家電 2   3万円台 3   テレビ 4   黒 5   SONY 6   三菱 商品とジャンルのリレーションテーブル、 item_genre item_id genre_id 1    1 1    2 1    3 2    1 2    3 2    4 2    6 ユーザーが希望する商品ジャンルのテーブル(ユーザーとジャンルのリレーションテーブル)、 user_genre user_id genre_id 1    1 1    3 2    1 2    3 2    4 3    1 3    3 3    4 3    5 以上があるとします。 この時に商品側から(商品IDを元に)、その商品を希望しているユーザーIDを取得する場合の SQL文の作成方法のご教示をお願いいたします。 上記のテーブルの例ですと、アイテム1から取得したいユーザーIDは1、アイテム2からは ユーザーID 1と2を取得できればOKです。 商品が持つジャンルIDが1,2,3に対してユーザーが希望するジャンルIDが1,3のように少ない 場合は対象にふくまれますが、商品が持つジャンルIDが1,3に対してユーザーが希望する ジャンルIDが1,3,4のように多くなる場合は対象に含めません。 色々と考えてみたのですが、頭がこんがらがってしまい迷宮に迷い込んでしまいました。 すみませんがお知恵をお貸しください。よろしくお願いします。 ※DBサーバーがMySQLのため、MySQLで実現できる方法だとありがたいです。

    • ベストアンサー
    • MySQL
  • 1000万件のデータをmysqlで効率良く扱いたい

    専門学校の制作でデータを格納・表示するものを作っています。 とはいっても、ブログみたいなアルゴリズムなので難しくはないです。 ただ、mysqlの構造をかんがえる時に疑問があります。 item table構造 id title body categoryid category table構造 id title 例えば、1000万件のデータを格納する時、 (1)1つのitem tableに1000万件のデータを格納して、 該当カテゴリーのもの一覧表示したり、 該当アイテムのものを表示したりする場合。 (2)item tableをカテゴリーごとに分ける。 cate1_item_table cate2_item_table 1つのtableには100万件のデータが入り、 cate**_item_tableは10個存在する。 この時、どちらのほうが負荷がかからないでしょうか。 どなたか詳しい方要らしゃれば教えていただけないでしょうか。 どうぞよろしくお願い致します。

    • ベストアンサー
    • MySQL
  • ストアドプロシージャでトランザクション処理をするにはどうすれば良いので

    ストアドプロシージャでトランザクション処理をするにはどうすれば良いのでしょうか? 複数のテーブルの行をストアドプロシージャで一括削除したいのですが、 エラーが発生した場合は、ロールバックしたいと思っています。 たとえば、 create table A (id INT, name VARCHAR(32)); // idと名前を持つテーブルA create table B (id INT, address TINYTEXT); // idと住所を持つテーブルB の二つのテーブル(idで紐付け)で、 Aの行が削除されたらBの行を削除するが、Bの削除でエラーが出た場合はAの削除をロールバックする。 という処理を行いたいのです。(ロールバックが可能であれば、ストアドプロシージャでなくても構いません。) どのように書けば良いのでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL