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

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

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

GROUP BYとはSQL文のひとつで、SELECT文において特定の列の値が等しい行ごとに表をグループ化します。

MySQL

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

SQL

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

Q&A

解決済

1回答

1365閲覧

チャットグループの最新メッセージを取得した上でグループの一覧を取得するSQLクエリ

退会済みユーザー

退会済みユーザー

総合スコア0

GROUP BY

GROUP BYとはSQL文のひとつで、SELECT文において特定の列の値が等しい行ごとに表をグループ化します。

MySQL

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

SQL

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

0グッド

0クリップ

投稿2021/05/25 09:14

前提・実現したいこと

MySQLを使用しています。
テーブル構造はこのような形です。
userテーブル

+-------------+-------------------------+------+-----+----------------------+--------------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------------------+------+-----+----------------------+--------------------------------+ | id | varchar(36) | NO | PRI | NULL | | | email | varchar(500) | YES | | NULL | | | name | varchar(500) | YES | | NULL | | password | varchar(500) | NO | | NULL | | | created_at | datetime(6) | NO | | CURRENT_TIMESTAMP(6) | | | updated_at | timestamp(6) | NO | | CURRENT_TIMESTAMP(6) | on update CURRENT_TIMESTAMP(6) | | +-------------+-------------------------+------+-----+----------------------+--------------------------------+

messageテーブル

+---------------+--------------------------------------+------+-----+----------------------+--------------------------------+ | Field | Type | Null | Key | Default | Extra | +---------------+--------------------------------------+------+-----+----------------------+--------------------------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | text | text | YES | | NULL | | | created_at | datetime(6) | NO | | CURRENT_TIMESTAMP(6) | | | updated_at | timestamp(6) | NO | | CURRENT_TIMESTAMP(6) | on update CURRENT_TIMESTAMP(6) | | chat_group_id | int(11) | YES | MUL | NULL | | | sender_id | varchar(36) | YES | MUL | NULL | | +---------------+--------------------------------------+------+-----+----------------------+--------------------------------+

groupテーブル

+------------+--------------+------+-----+----------------------+--------------------------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+----------------------+--------------------------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | | image_url | text | NO | | NULL | | | created_at | datetime(6) | NO | | CURRENT_TIMESTAMP(6) | | | updated_at | timestamp(6) | NO | | CURRENT_TIMESTAMP(6) | on update CURRENT_TIMESTAMP(6) | +------------+--------------+------+-----+----------------------+--------------------------------+

userとgroupの中間であるuser_chat_group_participationテーブル

+---------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------------+-------------+------+-----+---------+-------+ | user_id | varchar(36) | NO | PRI | NULL | | | chat_group_id | int(11) | NO | PRI | NULL | | +---------------+-------------+------+-----+---------+-------+

発生している問題・エラーメッセージ

この構成で、ユーザーが所属しているグループを最新メッセージのみ結合して取得したいのですが、
最新メッセージのみ結合するクエリがどうしても思いつきません。
お力添えいただきたいです。

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

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

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

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

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

sazi

2021/05/25 14:02

求めたい結果や条件を明示して下さい。 条件や駆動表を何にするかでコストも変わりますから。
guest

回答1

0

ベストアンサー

※テストデータもないので机上で考えただけです。無検証なのでご承知おきを。
※MySQL 8.0以上限定です。

次のような順序でクエリを組み立てましょう。
①指定ユーザーが所属するグループの一覧を取得

sql

1select user_id, chat_group_id 2from user_chat_group_participation 3where user_id = [指定のユーザーID]

このクエリの結果をQ1とします。
Q1で抽出したグループIDに紐づくメッセージを結合する。以下の例では全件結合している。
最新更新日時順に並びます。

sql

1select 2 Q1.chat_group_id 3 ,T1.id 4 ,T1.text 5 ,T1.updated_at 6from 7 Q1 8 JOIN message T1 9 ON T1.chat_group_id == Q1.chat_group_id 10order by update_at desc

③ ②のクエリに「chat_group_idごとに、更新順順位をつける」ウィンドウ関数を適用します。
グループごとの更新順がupdate_order_by_chat_group_idに入ります。

sql

1select 2 Q1.chat_group_id 3 ,T1.id 4 ,T1.text 5 ,T1.updated_at 6 ,row_number() over ( partition by Q1.chat_group_id, T1.updated_at order by T1.updated_at) as update_order_by_chat_group_id 7from 8 Q1 9 JOIN message T1 10 ON T1.chat_group_id == Q1.chat_group_id 11order by chat_group_id, update_at desc

このクエリをQ2とします。

Q2の結果からupdate_order_by_chat_group_idが1のものを抽出すれば、グループごとの最新メッセージが取得できます。

sql

1select 2 * 3from 4 Q2 5where 6 update_order_by_chat_group_id = 1

⑤ 上記の各クエリをwith句で接続して完成です。

sql

1with Q1 as ( 2 select user_id, chat_group_id 3 from user_chat_group_participation 4 where user_id = [指定のユーザーID] 5), Q2 as ( 6 select 7 Q1.chat_group_id 8 ,T1.id 9 ,T1.text 10 ,T1.updated_at 11 ,row_number() over ( partition by Q1.chat_group_id, T1.updated_at order by T1.updated_at) as update_order_by_chat_group_id 12 from 13 Q1 14 JOIN message T1 15 ON T1.chat_group_id == Q1.chat_group_id 16 order by chat_group_id, update_at desc 17) 18select 19 * 20from 21 Q2 22where 23 update_order_by_chat_group_id = 1

row_numberの使い方をきちんと理解できればクエリの組み立ては難しくないでしょう。

投稿2021/05/25 11:39

hope_mucci

総合スコア4447

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問