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

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

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

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

MariaDB

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

Q&A

解決済

3回答

3313閲覧

3つのテーブルをGROUP_CONCATでまとめたい

earnest_gay

総合スコア615

SQL

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

MariaDB

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

1グッド

1クリップ

投稿2016/06/27 05:19

編集2016/06/27 06:05

2つまでならできますが3つになるとできません...

①まずnameテーブルを基準にskillテーブルだけ結合します。
SELECT * FROM name
LEFET JOIN skill;
イメージ説明

②次にリレーション張ります。
SELECT * FROM name LEFT JOIN skill ON name.id=skill.user_id;
イメージ説明

③次に表示するカラム名を指定しておきます。
SELECT name.id, name,
skill.id, skill.user_id, skill,level
FROM name
LEFT JOIN skill ON name.id=skill.user_id;
イメージ説明

④GROUP BYでまとめます。
SELECT name.id, name,
skill.id, skill.user_id, skill, level
FROM name
LEFT JOIN skill ON name.id=skill.user_id
GROUP BY name.id;
イメージ説明

⑤skillが1つしか表示されないのでgroup_concatでまとめます。
SELECT name.id, name,
skill.id, skill.user_id, GROUP_CONCAT(skill), GROUP_CONCAT(level)
FROM name
LEFT JOIN skill ON name.id=skill.user_id
GROUP BY name.id;
イメージ説明

⑥更にitemテーブルも追加させたくなりました。
SELECT name.id, name,
skill.id, skill.user_id, GROUP_CONCAT(skill), GROUP_CONCAT(level)
FROM name
LEFT JOIN skill ON name.id=skill.user_id
LEFT JOIN item ON name.id=item.user_id
GROUP BY name.id;
イメージ説明

⑦表示がずれてしまったので⑤に戻りますが、
テーブルはname+itemにしてみます。
SELECT name.id, name,
item.id, item.user_id, GROUP_CONCAT(item), GROUP_CONCAT(num)
FROM name
LEFT JOIN item ON name.id=item.user_id
GROUP BY name.id;
イメージ説明

2つのテーブルまでなら、まとめることができますが
⑤と⑦をまとめるにはどうしたらよろしいでしょうか?

⑧試しに下記を試してみました。
SELECT name.id, name,
skill.id, skill.user_id, GROUP_CONCAT(skill), GROUP_CONCAT(level),
item.id, item.user_id, GROUP_CONCAT(item), GROUP_CONCAT(num)
FROM name
LEFT JOIN skill ON name.id=skill.user_id
LEFT JOIN item ON name.id=item.user_id
GROUP BY name.id
\G;

イメージ説明

同じskillが沢山入ってます。
あとからexplode()で配列を取得する予定なので、同じ名前はいらないのです。
ある分だけ欲しいので、最後の画像のもので言えばskillとlevelがある分だけ表示されてほしいのです。
それが必要なデータだからです。


例えば、こんな感じで使用したいのです。

$en = filter_input(INPUT_GET, 'EN'); $sql = "SELECT name.id, name AS 'キャラ名', GROUP_CONCAT(skill) AS '技',GROUP_CONCAT(level) AS 'レベル', GROUP_CONCAT(item) AS 'アイテム',GROUP_CONCAT(num) AS '個数' FROM name LEFT JOIN skill ON name.id = skill.user_id LEFT JOIN item ON name.id = skill.user_id WHERE name.id = '$en' GROUP BY name.id"; $stmt = $pdo->prepare($sql); $stmt->execute(); var_dump($sql); foreach ($stmt as $row) { echo '<br /><br />'; echo 'キャラ名:'.$row['キャラ名'].'<br />'; $skill =$row['技']; $skillArray = explode(",", $skill); $level =$row['レベル']; $levelArray = explode(",", $level); for($i = 0;$i < count($skillArray);$i++) { echo '<br />'; echo '技名:'.$skillArray[$i].'<br />'; echo 'レベル:'.$levelArray[$i].'<br />'; } $item =$row['アイテム']; $itemArray = explode(",", $item); $num =$row['個数']; $numArray = explode(",", $num); for($i = 0;$i < count($itemArray);$i++) { echo '<br />'; echo 'アイテム名:'.$itemArray[$i].' '.$levelArray[$i].'個<br />'; } } echo '<br />'; print_r($skillArray); echo '<br /><br />'; print_r($levelArray); echo '<br /><br />'; print_r($itemArray); echo '<br /><br />'; print_r($numArray);

↓結果(ここから)

キャラ名:ナルト

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

アイテム名:ポーション 15個

アイテム名:ポーション 15個

アイテム名:ハイポーション 20個

アイテム名:ハイポーション 20個

アイテム名:エリクサー 18個

アイテム名:エリクサー 18個

アイテム名:フェニックスの尾 36個

アイテム名:フェニックスの尾 36個

アイテム名:ポーション 52個

アイテム名:ポーション 52個

アイテム名:ハイポーション 21個

アイテム名:ハイポーション 21個

アイテム名:エリクサー 14個

アイテム名:エリクサー 14個

アイテム名:フェニックスの尾 55個

アイテム名:フェニックスの尾 55個

アイテム名:ラストエリクサー 22個

アイテム名:ラストエリクサー 22個

アイテム名:薬草 21個

アイテム名:薬草 21個

Array ( [0] => 螺旋丸 [1] => 螺旋手裏剣 [2] => 螺旋丸 [3] => 螺旋手裏剣 [4] => 螺旋丸 [5] => 螺旋手裏剣 [6] => 螺旋丸 [7] => 螺旋手裏剣 [8] => 螺旋丸 [9] => 螺旋手裏剣 [10] => 螺旋丸 [11] => 螺旋手裏剣 [12] => 螺旋丸 [13] => 螺旋手裏剣 [14] => 螺旋丸 [15] => 螺旋手裏剣 [16] => 螺旋丸 [17] => 螺旋手裏剣 [18] => 螺旋丸 [19] => 螺旋手裏剣 )

Array ( [0] => LV50 [1] => LV80 [2] => LV50 [3] => LV80 [4] => LV50 [5] => LV80 [6] => LV50 [7] => LV80 [8] => LV50 [9] => LV80 [10] => LV50 [11] => LV80 [12] => LV50 [13] => LV80 [14] => LV50 [15] => LV80 [16] => LV50 [17] => LV80 [18] => LV50 [19] => LV80 )

Array ( [0] => ポーション [1] => ポーション [2] => ハイポーション [3] => ハイポーション [4] => エリクサー [5] => エリクサー [6] => フェニックスの尾 [7] => フェニックスの尾 [8] => ポーション [9] => ポーション [10] => ハイポーション [11] => ハイポーション [12] => エリクサー [13] => エリクサー [14] => フェニックスの尾 [15] => フェニックスの尾 [16] => ラストエリクサー [17] => ラストエリクサー [18] => 薬草 [19] => 薬草 )

Array ( [0] => 15 [1] => 15 [2] => 20 [3] => 20 [4] => 18 [5] => 18 [6] => 36 [7] => 36 [8] => 52 [9] => 52 [10] => 21 [11] => 21 [12] => 14 [13] => 14 [14] => 55 [15] => 55 [16] => 22 [17] => 22 [18] => 21 [19] => 21 )

↑結果(ここまで)

本当はこう表示させたいのです。

キャラ名:ナルト

技名:螺旋丸
レベル:LV50

技名:螺旋手裏剣
レベル:LV80

アイテム名:ポーション 15個

アイテム名:ハイポーション 20個

アイテム名:エリクサー 18個

アイテム名:フェニックスの尾 36個

イメージ説明

user_id=2のしか持っていない薬草まで表示されてしまっているのでおかしいのです...

search_search👍を押しています

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

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

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

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

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

yambejp

2016/06/27 05:36

それぞれのtableの例示はcreate table形式で表示すると再現しやすい
earnest_gay

2016/06/27 06:06

>>tableの例示はcreate table形式で表示 どういうことでしょうか?
guest

回答3

0

前回回答した通り

select name,group_concat(concat(`skill_name`,',',`level`) separator ';') as skill from ・・・ group by name

が最も効率的なデータの取り出し方だと思います

PHP側で出てきたskillを「;」で分割後してforでまわしその中で
「,」で分割してul-liで表示してください

※ごめんなさい、転記ミスをなおしました

投稿2016/06/27 05:57

編集2016/06/27 08:48
yambejp

総合スコア114839

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

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

earnest_gay

2016/06/27 06:23

知識不足で仰られていることがよくわからないのですが (`skill_name`,',',`level`) separator ';') の分部が分かりません...
guest

0

ベストアンサー

クエリを横にずらっと並べて書くと非常にわかりづらいと思います。
LEFT JOIN をするのは結構ですが、何が欲しいのか目的がわかりづらいので、次のような感じで書いてみてはどうでしょうか。
テーブルに何があるのか読み取るのが大変だったので適当ですが…。

SQL

1SELECT name.id, name, skills, levels FROM name 2 LEFT JOIN (select GROUP_CONCAT(skill) AS skills group by user_id) SK ON name.id=SK.user_id 3 LEFT JOIN (select GROUP_CONCAT(level) AS levels group by user_id) LV ON name.id=LV.user_id

クエリ自体は未検証です。間違ってたらすみません。

投稿2016/06/27 05:39

ttyp03

総合スコア16998

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

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

earnest_gay

2016/06/27 06:07

読みづらくてすいません。 修正追加させて頂きました。
ttyp03

2016/06/27 07:03 編集

こちらの回答を待たずとも自力で試していただきたかったですが、先に書いてみました(未検証) select name.id, name, skills, levels, items, nums from name left join (select group_concat(skill) as skills, group_concat(level) as levels from skill group by user_id) SK on name.id=SK.user_id left join (select group_concat(item) as items, group_concat(num) as nums from item group by user_id) IT on name.id=IT.user_id これでうまくできれば、あとはPHP側でexplodeで分解するなどすればよいかと思います。
earnest_gay

2016/06/27 09:07

ありがとうございます! JOINの仕組みが理解できていない状態でJOINを多用しようとした結果 余計に難しいことをしようとしていました。 それぞれのSQL文にすることで解決しそうです。
guest

0

投稿2016/06/27 05:31

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

退会済みユーザー

総合スコア0

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

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

earnest_gay

2016/06/27 06:29

うまくいきません... MariaDB [test]> SELECT DISTICT name.id, name AS 'キャラ名', -> GROUP_CONCAT(skill) AS '技',GROUP_CONCAT(level) AS 'レベル', -> GROUP_CONCAT(item) AS 'アイテム',GROUP_CONCAT(num) AS '個数' -> FROM name -> LEFT JOIN skill ON name.id = skill.user_id -> LEFT JOIN item ON name.id = skill.user_id -> WHERE name.id =1 -> GROUP BY name.id -> \G; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.id, name AS 'キャラ名', GROUP_CONCAT(skill) AS '技',GROUP_CONCAT(level) A' at line 1 ERROR: No query specified
退会済みユーザー

退会済みユーザー

2016/06/27 06:31

シンタックスエラーというのは単なる文法違反です。ルールに従って書き直してください。オレオレルールをごり押ししてもうまくいきません。
attakei

2016/06/27 08:10

> Kosuke_Shibuya さん distict ではなく、distinct ではないでしょうか
退会済みユーザー

退会済みユーザー

2016/06/27 08:18

attakeiさん スペルミスしてましたね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問