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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

Q&A

解決済

1回答

1008閲覧

言語別レコードに備えたテーブル設計とPHP取得コード

ningen

総合スコア1

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

0グッド

1クリップ

投稿2020/08/10 12:17

編集2020/08/11 01:30

質問事項

投稿に言語別タイトルを実装しています。

以下PHPで、言語別タイトルが取得できるかどうか知りたいです。

$his_lang_title = $titles[$key]; // ← ここでズレないかを特に懸念しています

とあるように、このPHPでは$titlesと$lang_idsが言語ごとに同じ位置に来ないと適切に取得できないと思うのですが、以下のSQLのSELECTは、それを同じ位置に取得できるでしょうか?

実際に何度試してもできましたが、例えばORDER BYを書かないと取得の順番が変化するという稀なケースもございますから、そういった稀なケースがもしこのSQLでも起こるのであれば、PHPでの取得もズレてしまうことになりますので懸念しています。

・同じ順番で取得できるから大丈夫
・稀にズレるからこうした方がいい
といったアドバイスを頂戴したく思っています。

SQL

テーブル設計およびレコード取得のSQLはこうなっています。

SQL

1# 言語マスタ 2CREATE TABLE IF NOT EXISTS m_langs ( 3 `ID` INT(2) UNSIGNED, 4 `lang` VARCHAR(10) NOT NULL, 5 PRIMARY KEY (`ID`) 6); 7INSERT INTO m_langs (`ID`,`lang`) 8VALUES (1,'ja'),(2,'en'),(3,'zh'),(99,'xx'); # 投稿時に言語指定がなければ99が入る 9 10# 投稿 11CREATE TABLE IF NOT EXISTS d_posts ( 12 `ID` INT(10) UNSIGNED AUTO_INCREMENT, 13 `user_ID` INT(10) UNSIGNED NOT NULL, 14 PRIMARY KEY (`ID`) 15); 16INSERT INTO d_posts (`user_ID`) 17VALUES (100),(200),(300); 18 19# 言語別タイトル 20CREATE TABLE IF NOT EXISTS d_post_titles ( 21 `post_ID` INT(10) UNSIGNED, 22 `lang_ID` INT(2) UNSIGNED NOT NULL, 23 `title` VARCHAR(100) CHARACTER SET utf8mb4 NOT NULL, 24 CONSTRAINT foreign_key_post_ID FOREIGN KEY (`post_ID`) REFERENCES d_posts(`ID`), 25 CONSTRAINT foreign_key_lang_ID FOREIGN KEY (`lang_ID`) REFERENCES m_langs(`ID`) 26); 27INSERT INTO d_post_titles (`post_ID`,`lang_ID`,`title`) 28VALUES 29(1,1,'りんご'), (1,2,'apple'), (1,3,'苹果'), 30(2,1,'ばなな'), (2,2,'banana'), 31(3,99,'mandarine'); 32

SQL

1SELECT 2 posts.ID AS post_id, 3 GROUP_CONCAT(post_titles.title separator ',') as titles, 4 GROUP_CONCAT(post_titles.lang_id separator ',') as lang_ids 5 6FROM 7 d_posts posts 8 LEFT JOIN d_post_titles post_titles ON post_titles.post_ID=posts.ID 9 10WHERE 11 posts.ID = 1 12 13GROUP BY 14 posts.ID 15

PHP

言語別タイトルを取得するPHPはこちらです。

PHP

1/* 2上記SQLの結果です 3このように「りんご」の位置に「1」が来て「apple」の位置に「2」が来れば 4$his_lang_title = $titles[$key]; 5で取得できるのですが… 6この順番は上記SQLでズレることはないでしょうか? 7*/ 8$rows = array( array( 9 "post_id" => "1", 10 "titles" => "りんご,apple,苹果" 11 "lang_ids" => "1,2,3" 12)); 13$row = $rows[0]; 14 15/* 16当該ユーザの言語($his_lang_id)に応じたタイトルを取得します 17*/ 18// 当該ユーザの言語 19$his_lang_id = 1; 20// 言語別情報 21$titles = explode( ',', $row['titles'] ); 22$lang_ids = explode( ',', $row['lang_ids'] ); 23// 表示したい言語ID 24$print_lang_id = null; 25if( in_array( (string)$his_lang_id, $lang_ids, true ) ){ 26 $print_lang_id = $his_lang_id; // 当該ユーザの言語があればそれを出力 27}else{ 28 if( in_array( '2', $lang_ids, true ) ){ 29 $print_lang_id = 2; // 当該ユーザの言語がなく、2(en) があればそれを出力 30 } 31} 32// 表示したいタイトル 33$key = array_search( $print_lang_id, $lang_ids ) ?? 0; // 当該ユーザの言語がなく、2(en) もなければ最初のもの(0個目)を出力 34$his_lang_title = $titles[$key]; // ← ここでズレないかを特に懸念しています 35$result['当該ユーザの言語($his_lang_id)に応じたタイトル'] = $his_lang_title;

補足情報(FW/ツールのバージョンなど)

環境は
Z.comサーバー Zeroプラン
MySQL 5.7.2
PHP 7.3
です。

長文で素人コードにつき見にくい点など多々あるかと思いますが、宜しくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

ご提示いただいたSQLでは、ご懸念通り、順序が保証されません。

GROUP_CONCAT()では、ソートが指定できますので、順序が保証されるように、以下のようにされると良いかと思います。

SQL

1SELECT 2 posts.ID AS post_id, 3 GROUP_CONCAT(post_titles.title 4 ORDER BY post_titles.lang_id 5 separator ',') as titles, 6 GROUP_CONCAT(post_titles.lang_id 7 ORDER BY post_titles.lang_id 8 separator ',') as lang_ids 9(以下略)

GROUP_CONCAT

投稿2020/08/11 06:27

YT0014

総合スコア1750

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

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

ningen

2020/08/12 01:43

やはり保証されませんでしたか、気がついてよかったです。適切な方法をどうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問