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

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

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

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

SQL

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

Q&A

解決済

2回答

517閲覧

INNER JOIN の順序の通りに取得したい

nikuatsu

総合スコア177

MySQL

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

SQL

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

0グッド

0クリップ

投稿2022/06/15 13:55

編集2022/06/16 05:13

前提

MySQLで「指定色のフルーツを、いいね順で検索」する機能を実装しています。

実現したいこと

いいね順での取得を実現したいです。

発生している問題

いいね順という点が上手くできません。

該当のソースコード

こちらになりまして、「赤い色のフルーツ」の取得まではできているのですが、それが 1,6,8,10 という順序になってしまいます。

いいね順が目的なので、10,6,8,1 という順序にしたいのです。

サブクエリsearchedORDER BY fruits2.count_likes DESCをかけていいね順にしているのに、なぜでしょうか?

以下実行サンプル:http://sqlfiddle.com/#!9/52257e/2

SQL

1CREATE TABLE my_fruits 2(`ID` int, `count_likes` int(100), `content` varchar(100)); 3INSERT INTO my_fruits 4(`ID`, `count_likes`, `content`) 5VALUES 6(1, 10, 'フルーツ1'), 7(2, 56, 'フルーツ2'), 8(3, 36, 'フルーツ3'), 9(4, 94, 'フルーツ4'), 10(5, 12, 'フルーツ5'), 11(6, 80, 'フルーツ6'), 12(7, 90, 'フルーツ7'), 13(8, 46, 'フルーツ8'), 14(9, 70, 'フルーツ9'), 15(10, 88, 'フルーツ10'); 16 17CREATE TABLE my_tags 18(`ID` int, `tag_kind_id` int, `tag_name` varchar(100)); 19INSERT INTO my_tags 20(`ID`, `tag_kind_id`, `tag_name`) 21VALUES 22(1, 1, '濃い赤'), 23(2, 1, '薄い青'), 24(3, 1, '明るい緑'), 25(4, 1, 'かわいいピンク'), 26(5, 1, '灰色'), 27(6, 1, '真っ青'), 28(7, 1, '薄い赤'), 29(8, 1, '暗黒'), 30(9, 1, '黄色'), 31(10, 1, '紫'), 32(11, 1, 'オレンジ'); 33 34CREATE TABLE my_tag_holders 35(`fruits_ID` int, `tags_ID` int); 36INSERT INTO my_tag_holders 37(`fruits_ID`, `tags_ID`) 38VALUES 39(1, 1),(1, 2),(1, 3), 40(2, 4),(2, 5),(2, 6),(2, 9), 41(3, 3), 42(4, 4),(4, 5),(4, 6), 43(5, 8), 44(6, 1),(6, 2),(6, 3), 45(7, 10), 46(8, 7),(8, 9), 47(9, 4),(9, 5),(9, 6), 48(10, 7),(10, 10);

SQL

1SELECT fruits.ID AS fruits_id 2 ,fruits.count_likes 3 ,fruits.content 4 ,GROUP_CONCAT( 5 tags.tag_name 6 ) AS tag_names 7 8FROM my_fruits fruits 9 10 -- 赤い色のフルーツをいいね順で取得 11 INNER JOIN ( 12 13 SELECT fruits2.ID 14 FROM my_fruits fruits2 15 16 LEFT JOIN my_tag_holders th 17 ON th.fruits_ID = fruits2.ID 18 LEFT JOIN my_tags tags2 19 ON tags2.ID = th.tags_ID 20 21 WHERE tags2.tag_name LIKE '%赤%' 22 23 GROUP BY fruits2.ID 24 ORDER BY fruits2.count_likes DESC, fruits2.ID DESC 25 LIMIT 0, 20 26 27 ) AS searched ON searched.ID = fruits.ID 28 29 LEFT JOIN my_tag_holders th 30 ON th.fruits_ID = fruits.ID 31 LEFT JOIN my_tags tags 32 ON tags.ID = th.tags_ID 33 34GROUP BY searched.ID

試したこと

サブクエリの INNER JOIN の中身だけで実行すると、正しく 10,6,8,1 という順序になっていることが確認できました。(ならそれを INNER JOIN している上記クエリがなぜ 1,6,8,10 という順序になるのか疑問です。)

また次のように、INNER JOIN の結果にもう一度改めて ORDER BY をかける(35行目を追加する)ならば正しい順序となりましたが、しかし改めてかける点に違和感を覚えています。

SQL

134行目: GROUP BY searched.ID 2 3-- ↓INNER JOINの結果にもう一度改めてORDER BYをかける 4 534行目: GROUP BY searched.ID 635行目: ORDER BY fruits.count_likes DESC, fruits.ID DESC

改めて ORDER BY かけることなく、INNER JOIN の順序そのままに取得できないでしょうか?

補足情報

MySQL5.7 を利用しています。

(MySQL8.0 ならば「Join-Order オプティマイザヒント句」なるものが有効っぽい(?)というのは こちらの記事 で見つけたですが…)

追記

検索結果は上記のように INNER JOIN を用いてsearchedとして得たいです。
searchedを作らず、WHERE で取得する方法も試したのですが、それは取得に時間がかかったためです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

また次のように、INNER JOIN の結果にもう一度改めて ORDER BY をかける(35行目を追加する)ならば正しい順序となりましたが、しかし改めてかける点に違和感を覚えています。
改めて ORDER BY かけることなく、INNER JOIN の順序そのままに取得できないでしょうか?

できません。
order byをつけない場合のselectの結果は、どんな順番で取得されてもいいという仕様になっています。
order byをつけないとシステム側の都合で勝手に決められた順番でレコードが取得されますので、特定の順番でレコードを取得したい場合はorder byをつけてください。

Order by - Wikipedia

ORDER BY is the only way to sort the rows in the result set. Without this clause, the relational database system may return the rows in any order.

ORDER BYは、結果セットの行を並べ替える唯一の方法です。この句がないと、リレーショナルデータベースシステムは任意の順序で行を返す可能性があります。

投稿2022/06/15 17:58

編集2022/06/15 18:06
ku__ra__ge

総合スコア4524

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

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

nikuatsu

2022/06/15 20:13

詳しくリンクまでどうもありがとうございます。諦めがつきました。
guest

0

SELECT句の中にサブクエリを書くというやり方で実現できるかと思います。

SQL

1SELECT 2 F.ID AS fruits_id, 3 F.count_likes AS count_likes, 4 F.content AS content, 5 (SELECT GROUP_CONCAT(T.tag_name) 6 FROM my_tag_holders AS H 7 JOIN my_tags AS T ON H.tags_ID = T.ID 8 WHERE F.ID = H.fruits_ID) AS tag_names 9FROM my_fruits AS F 10JOIN my_tag_holders AS H ON F.ID = H.fruits_ID 11JOIN my_tags AS T ON H.tags_ID = T.ID 12WHERE T.tag_name LIKE '%赤%' 13GROUP BY fruits_id 14ORDER BY count_likes DESC, fruits_id DESC 15LIMIT 0, 20

投稿2022/06/15 15:16

neko_the_shadow

総合スコア2225

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

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

nikuatsu

2022/06/15 16:26

ご回答誠にありがとうございます。 追記したのですが、そちら試させて頂きますと、SELECT句の中のサブクエリに時間がかかってしまいました。 質問の INNER JOIN は WHERE tags2.tag_name LIKE '%赤%' によって絞り込まれたものだけがJOINされますが、 そちらは WHERE F.ID = H.fruits_ID によってとりあえず全件をJOINしてしまうせいだと思います。 しかしSELECT句の中にサブクエリを書くというやり方自体を知りませんでしたのでその点大変勉強になりました。今後の参考にさせて頂きます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問