質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Q&A

解決済

3回答

1393閲覧

3つのテーブルの情報を取得して表示させたい

earnest_gay

総合スコア615

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

0グッド

0クリップ

投稿2016/06/27 07:35

要点をまとめて質問します。
釣り方を学ぶのも大切ですが、今は一刻も早く餌が欲しいです。
餌からどんな魚が釣れるか逆算して学ぶタイプです。

本題です。

3つのシンプルなテーブルがあります。

●nameテーブル
イメージ説明

●skillテーブル
イメージ説明

●itemテーブル
イメージ説明

先に申し上げますとブラウザにはこのように表示させたいです。

キャラ名:ナルト

技 レベル
ナルトの技1 LV50
ナルトの技2 LV80

所持アイテム
user_id1のアイテムその1
user_id1のアイテムその2
user_id1のアイテムその3
user_id1のアイテムその4


キャラ名:サスケ

技 レベル
サスケの技1 LV25
サスケの技2 LV50
サスケの技3 LV90

所持アイテム
user_id2のアイテムその1
user_id2のアイテムその2
user_id2のアイテムその3
user_id2のアイテムその4
user_id2のアイテムその5


1つのページにナルトもサスケも表示させたいわけじゃなくて
?chara=1とか?chara=2とか$_GETして表示させたいので
1ページ1キャラの詳細を表示させたいのです。

$chara = filter_input(INPUT_GET, 'chara');
という風に用意しておいてWHERE句に name.id = '$chara'とかで処理できると思います。

色々書きすぎると、回答者になにを知りたいのか混乱させてしまうかもなので、
まずは上記のようにブラウザに表示させたいです。

実際躓いているのは、ナルトとサスケは技の取得数も違えば持っているアイテム数も違います。
それをSQLでどう取得して、1つのぺージでどう表示させるかというところだと思います。

こちらでも質問させていただいてますが、今回かなり苦戦しております。
https://teratail.com/questions/39276
https://teratail.com/questions/39286

SQL文とPHPでの表示ソースがあるとじっくり読み解いていきたいのですが...
宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

これがみなさんが何度も提示している「JOINでやらずに各テーブルを引けばいい」という魚です。
魚から逆算するとのことですので、魚を与えました。しかし、この技術に関して再度質問することを禁じます。再度質問しても、この魚から得られる疑問に対しては私は回答しません。

PHP

1// まず名前一覧を取る 2$namesStmt = $pdo->query("SELECT * FROM name"); 3 4// 名前一覧でforeachする 5foreach ($namesStmt as $nameRow) { 6 7 // 名前に関わる情報を出力する 8 echo "キャラ名:".$nameRow['name']; 9 10 // 技一覧を出力する前に、ヘッダにあたる部分を出力する 11 echo "技 レベル"; 12 13 // 名前のidにより技一覧を取得する 14 $skillStmt = $pdo->prepare("SELECT * FROM skill WHERE user_id = ?"); 15 $skillStmt->execute([$nameRow['id']]); 16 17 // 技一覧でforeachする 18 foreach($skillStmt as $skillRow) { 19 20 // 技に関わる情報を出力する 21 echo $skillRow['skill'].' '.$skillRow['LEVEL']; 22 } 23 24 // アイテム一覧を出力する前に、ヘッダにあたる部分を出力する 25 echo "所持アイテム"; 26 27 // 名前のidによりアイテム一覧を取得する 28 $itemStmt = $pdo->prepare("SELECT * FROM item WHERE user_id = ?"); 29 $itemStmt->execute([$nameRow['id']]); 30 31 // アイテム一覧でforeachする 32 foreach($itemStmtas $itemRow) { 33 34 // 技に関わる情報を出力する 35 echo $itemRow['item']; 36 } 37}

投稿2016/06/27 08:06

masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/06/27 08:49

回答ありがとうございます。 何度も似たような質問してしまい、理解が追い付かず回答者の手を煩わせてしまってすみません。
guest

0

ベストアンサー

だから、理屈わかんないのにjoinを使うからだとおもいますよ。
join使うのが目的ならともかく、
そういう画面を出したいのが目的なら、なんで手段を変えようとしないのでしょう?
手っ取り早く餌食って結果が出ると思いますよ。

idでnameテーブルを引く、
user_idで、skillテーブルを引く
user_idで、itemテーブルを引く

それで終わりますよ。

投稿2016/06/27 07:48

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/06/27 08:10

このアドバイスのおかげで出来たいことができました。 JIONしてやるものだと思っていたため、別の手段は思いつきませんでした。 その別の手段が今まで使っていたものだったなんて... ありがとうございました!
guest

0

先に申し上げますとブラウザにはこのように表示させたいです。

この2人の情報をまとめて1ページに表示したいのなら、JOINするアプローチでいいでしょう。
2人の情報をそれぞれ1ページずつに表示したいのなら、JOINするのはナンセンス。

条件によって回答が変わるので、「餌」をくれと言われても、あげようがないということです。

投稿2016/06/27 07:58

編集2016/06/27 08:00
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/27 08:11

それに、技術で飯食ってる人に対して、「ただ働きしてくれ」と言っていることとぽな時だということ、わかりませんかね…。 ソースコードが欲しいなら、予算と納期を提示してください。
earnest_gay

2016/06/27 08:12

回答ありがとうございます。 下の方のアドバイスのおかげで思っている表示ができるようになりました。 ただ、ネストが多いような気がするので、もし差し支えなければ添削といいますか、ここはこうした方がいいよなどありましたら、教えてくださるとたすかります。 $en = filter_input(INPUT_GET, 'EN'); $sql_name = "SELECT name.id,name FROM name WHERE name.id = '$en' "; $stmt_name = $pdo->prepare($sql_name); $stmt_name->execute(); $sql_skill = "SELECT skill.id,skill,level FROM skill WHERE skill.user_id = '$en' "; $stmt_skill = $pdo->prepare($sql_skill); $stmt_skill->execute(); $sql_item = "SELECT item.id,item FROM item WHERE item.user_id = '$en' "; $stmt_item = $pdo->prepare($sql_item); $stmt_item->execute(); /*$sql = "SELECT name.id, name AS 'キャラ名', GROUP_CONCAT(skill) AS '技',GROUP_CONCAT(level) AS 'レベル' FROM name LEFT JOIN skill ON name.id = skill.user_id WHERE name.id = '$en' GROUP BY name.id";*/ foreach ($stmt_name as $row) { echo '<br /><br />'; echo 'キャラ名:'.$row['name'].'<br />'; foreach ($stmt_skill as $row) { $skill =$row['skill']; $skillArray = explode(",", $skill); $level =$row['level']; $levelArray = explode(",", $level); for($i = 0;$i < count($skillArray);$i++) { echo '<br />'; echo '技名:'.$skillArray[$i].'<br />'; echo 'レベル:'.$levelArray[$i].'<br />'; } } foreach ($stmt_item as $row) { $item =$row['item']; $itemArray = explode(",", $item); for($i = 0;$i < count($itemArray);$i++) { echo '<br />'; echo '技名:'.$itemArray[$i].'<br />'; } } }
退会済みユーザー

退会済みユーザー

2016/06/27 08:15

いつまで、こんなコード書いているんでしょうか。以前に教えたことが全く身についていないではありませんか。 つくづく、残念に思いますし、馬鹿にされている気にさえなってきます。
earnest_gay

2016/06/27 08:35 編集

1度学んだことをずっと保持しておくのは長年の経験者ならではだと思い、こういうのは長年することで身につくものだと思うのですが...以前教えて頂いた部分はどこのところでしょうか?Shibuyaさんのいう「こんなコード」でも頭悩ませてやってるんです。 とりあえずやってみて出来たから、「これどうですか?」と尋ねることで気分を害されるのでしたら何も言えませんよ? いつも何かしらの回答やアドバイス頂いていることには感謝しています。 >>予算と納期を提示してください ここに参加してまだ間もないですが、ここはLancersではありませんよね...
退会済みユーザー

退会済みユーザー

2016/06/27 09:04 編集

その通りです。長年の努力と(時間的、金銭的コストの)投資の結果です。 それを大幅なショートカットで答えを手に入れたいということでしょ。 だったら、せめて教えたことは理解して欲しいものです。 問題の部分はこれですね↓ $sql_name = "SELECT name.id,name FROM name WHERE name.id = '$en' "; SQL文の中に$がはいるのは明らかに間違い。 自分のコメント言葉遣いに全く遠慮しないのできつくは感じるでしょうけど、コードに対する評価しかしません。 「このコードどうですか」に対する評価が「このコードはクソです」ということです。 最初の1行目、SQLの中に変数が直接書き込まれているだけで、セキュリティ上の問題があり、それ以外の部分がどうであろうと、「0点」です。
earnest_gay

2016/06/27 09:02

確かに、自分が教える立場で教えた人が同じことしていたら、「なんで同じことやってるんだ?理解してないのか?なんか残念だ...」ってなると思います。 その点、理解が追い付かず申し訳ございません。 プログラムの処理の方に問題があると思っていたのですが、SQL文の方でしたか... 直近のことなので覚えています。 下記はShibuyaさんに回答いただいたものですがこれはいいのでしょうか? $start = 10; $sql = sprintf("SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT %d, 5", $start); --------------------------------------------------------------- https://teratail.com/questions/39201より $EN = filter_input(INPUT_GET, 'EN'); $sql = sprintf("SELECT * FROM user_data WHERE id = %d"$EN) に対して Kosuke_Shibuya Kosuke_Shibuya 2016/06/26 16:46 sprintfは使っちゃいけない場面ですよ。 とのことだと思うのですが、これは何故sprintf使ってはいけないのでしょうか? 混同して覚えているのかもしれません...
退会済みユーザー

退会済みユーザー

2016/06/27 09:17 編集

Skypeでも使えば教えるのも楽なんですけどねー コメント欄だと、面倒極まりないですね…。 基本的にSQLはプリペアドステートメントで行いましょうというのが大原則です。 なのでいかなる場合も :filed とか ? とかで値を割り当てましょう。が大正解。 ただし、LIMIT 句に割り当てたい場合、文字列の割り当てだと問題が起きるので、sprintf という方法もありえますよ。でも bindValue を使う方が原則に従っていてその方が望ましいね。 ということです。 どう使うのか、も影響することおなので何が正解とかはありません。ただしセキュッリティの観点からやっちゃいけないというものは存在します。 http://qiita.com/ShibuyaKosuke/items/0c5c6df1fac218fbca38
earnest_gay

2016/06/27 09:26 編集

分かりました。 解説ありがとうございます。 >>文字列の割り当てだと問題が起きるので 下記のように整数にすれば、文字列の割り当て問題を回避できると思いますが 基本的にSQL文の中に変数が入るのはおかしいと覚えておきます。 $en = (INT)filter_input(INPUT_GET, 'EN'); 先々、検索機能の実装も考えているのでリンク先参考にさせていただきます。 ありがとうございます。
退会済みユーザー

退会済みユーザー

2016/06/27 09:27 編集

$en = (INT)filter_input(INPUT_GET, 'EN'); これでは不十分ですけど… 回避できると判断した理由がわかりませんね。 ああ、(int) キャストしてるか。大丈夫っちゃ大丈夫だけど…プレースホスダを利用しないなら、prepare execute を使っているのもおかしいですよね。
earnest_gay

2016/06/27 09:31

>>回避できると判断した理由がわかりませんね。 セキュリティー上の問題が起きるということは分かりました。 具体的にどんな問題が起きるのかは分りませんが、 文字列の割り当てだと問題が起きるということですので 逆に言えば文字列でなければ問題は起こらないと捉えました。
退会済みユーザー

退会済みユーザー

2016/06/27 09:35

「SQLインジェクション」で検索してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問