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

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

新規登録して質問してみよう
ただいま回答率
85.48%
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回答

3840閲覧

複数テーブルからのランダム取得を一回のSQLで行いたい

megmilk

総合スコア10

MySQL

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

SQL

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

0グッド

0クリップ

投稿2017/09/01 02:49

下記のような2つのテーブルがあります。
ランダムに取得した10ユーザーのメッセージを1件ずつランダムに取得
といった事はSQL一回で可能でしょうか。

メッセージを単純にユーザーIDでGROUP BYして
ランダムに返ってきてくれればいいんですが
暗黙的なソートが働くためか毎回同じ値が返ってきてしまいます。

ユーザーテーブル

ユーザーID, 名前, 登録日時

メッセージテーブル

メッセージID, メッセージ, ユーザーID, 登録日時

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

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

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

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

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

guest

回答2

0

以下でどうでしょうか?
元データ

SQL

1create table mes( 2message_id int unique key, 3message varchar(100), 4user_id int, 5created datetime 6); 7insert into mes values 8(1,'mes1',1,'2017-09-01 00:00:00'), 9(2,'mes2',1,'2017-09-01 00:00:01'), 10(3,'mes3',2,'2017-09-01 00:00:02'), 11(4,'mes4',1,'2017-09-01 00:00:03'), 12(5,'mes5',3,'2017-09-01 00:00:04'), 13(6,'mes6',2,'2017-09-01 00:00:05'), 14(7,'mes7',3,'2017-09-01 00:00:06'), 15(8,'mes8',4,'2017-09-01 00:00:07'), 16(9,'mes9',5,'2017-09-01 00:00:08');

抽出

SQL

1select * from mes as t3 2inner join ( 3select substring_index(group_concat(message_id order by rand()),',',1) as message_id 4from mes as t1 5where exists (select user_id from (select distinct user_id from mes order by rand() limit 3 ) as t2 where t1.user_id=t2.user_id) 6group by user_id 7) as t4 on t3.message_id=t4.message_id 8order by rand();

投稿2017/09/01 03:32

yambejp

総合スコア114827

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

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

megmilk

2017/09/01 04:30

回答ありがとうございます。 GROUP_CONCATの存在を知らなかったのでとても参考にさせて頂きました。 ただ、さすがにSQLが複雑になりすぎるので下記に省略してみました。 concatした結果からアプリ側でランダムに1件取得するのは それほどコストはかからないと思うのでコレがベストではないかなと思っています。 SELECT *, GROUP_CONCAT(message_id) as concat FROM mes GROUP BY user_id ORDER BY RAND() LIMIT 3
yambejp

2017/09/01 04:49

インデックスの貼り方とデータ量によってどの手法が効率的かは かわってくるかもしれませんね saziさんの提示されたソースはわかりやすく簡潔なロジックなので 検証してみて下さい
guest

0

ベストアンサー

幾つかの手法があります。
こちら(MySQLでランダムにレコードを取得する場合の手法)が参考になるかと。

追記

試してみていませんが、上記中RAND()を使った手法で

SQL

1select * 2 , ( 3 select `メッセージ` from `メッセージテーブル` 4 where `ユーザーid`=usr.`ユーザーid` 5 order by rand() limit 1 6 ) as `メッセージ` 7from `ユーザーテーブル` as usr 8order by rand() 9limit 10

メッセージテーブルの全体を取得したい場合は、メッセージテーブルの主キーに該当するものを取得すればいいのですが、この場合、ユーザーIDと登録日時だと思われるので、登録日時をサブクエリーで取得してさらに結合します。

SQL

1select * 2from ( 3 select * 4 , ( 5 select `登録日時` from `メッセージテーブル` 6 where `ユーザーid`=usr.`ユーザーid` 7 order by rand() limit 1 8 ) as `メッセージ登録日時` 9 from `ユーザーテーブル` as usr 10 order by rand() 11 limit 10 12 ) as v1 inner join `メッセージテーブル` msg 13 on v1.`ユーザーid`=msg.`ユーザーid` and v1.`メッセージ登録日時`=msg.`登録日時`

投稿2017/09/01 03:05

編集2017/09/01 04:31
sazi

総合スコア25184

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

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

megmilk

2017/09/01 03:30

回答ありがとうございます。 この記事は主にパフォーマンスの観点からランダム取得の手法を紹介しているもののようで この記事を読んでもちょっと私にはわからなかったです。
sazi

2017/09/01 04:11

追記してみました。
megmilk

2017/09/01 05:52

回答ありがとうございます。 最初の例で問題なくランダムなデータ取得が可能でしたのでベストアンサーにさせて頂きます。 この副問合せはちょっと盲点でした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問