🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
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回答

613閲覧

SQLで重複を除いたパフォーマンスの良いSQL文について

soba_umasugi

総合スコア1

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/02/27 06:22

編集2021/02/27 13:49

前提・実現したいこと

以下のメッセージテーブルから、自分がやりとりした相手一覧と、時間、ユーザ情報を取得したいです。
to_user_id,from_user_idから、自分に送られてきたメッセージ、また自分が送ったメッセージをgroupし一覧で取得し、messageテーブルの作成日、メッセー文章、ユーザ情報を取得したいです。

messageテーブル |----+------------+--------------+-----------+-----------------| | id | to_user_id | from_user_id | message | created_at | |----+------------+--------------+-----------+-----------------| | 1 | 1 | 2 | こんちわ! | 2021/1/1 00:01 | | 2 | 2 | 3 | こんちわ! | 2021/1/3 00:02 | | 3 | 3 | 4 | こんちわ! | 2021/1/2 00:03 | | 4 | 4 | 5 | こんちわ! | 2021/1/4 00:03 | | 5 | 5 | 1 | こんちわ! | 2021/1/5 00:03 | | 6 | 1 | 2 | こんちわ! | 2021/1/10 00:33 | | 7 | 3 | 2 | こんちわ! | 2021/1/11 20:00 | | 8 | 3 | 2 | こんちわ! | 2021/1/10 10:03 | | 9 | 2 | 3 | こんちわ! | 2021/1/2 01:03 | | 10 | 5 | 1 | こんちわ! | 2021/1/4 02:03 | |----+------------+--------------+-----------+-----------------|
user table |----+------------| | id | name | |----+------------| | 1 | みっちゃん | | 2 | なっちゃん | | 3 | タカハシ | | 4 | りょうた | | 5 | うさみ | |----+------------|

試したこと

sql文で以下を実行し、userテーブルを軸に、messageテーブルをつなげ取得することができましたが、messageテーブルの作成日、messageを追加すると同じユーザが重複して取得されてしまいます。ユーザはあくまでも1つで最新のmessageが紐付けられた状態で取得したいです。

select * from user join ( SELECT DISTINCT CASE WHEN to_user_id = 2 THEN from_user_id ELSE to_user_id END as userid,message.created_at FROM message WHERE from_user_id = 2 OR to_user_id = 2 ORDER BY created_at desc ) msg on msg.userid = user.system_user_id

どうぞよろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ユーザ2がやりとりしたメッセージのうち、相手ごとの最新メッセージが欲しいということでしょうか? たとえばユーザ2とユーザ3が2021/01/01と2021/02/01の2回やり取りしていた場合、2021/02/01のメッセージデータだけが欲しいという理解です。

であれば、例えば以下のようなSQLで実現することができます。

SQL

1WITH 2s AS ( 3 SELECT 4 id, 5 CASE WHEN from_user_id = 2 THEN to_user_id ELSE from_user_id END AS user_id, 6 message, 7 created_at 8 FROM message 9 WHERE from_user_id = 2 OR to_user_id = 2 10), 11t AS ( 12 SELECT 13 id, 14 user_id, 15 message, 16 created_at, 17 RANK() OVER(PARTITION BY user_id ORDER BY created_at DESC) AS RNK 18 FROM s 19) 20SELECT 21 t.id, 22 t.user_id, 23 u.name, 24 t.message, 25 t.created_at 26FROM t 27JOIN user AS u ON t.user_id = u.id 28WHERE RNK = 1;

まずユーザ2とやり取りしたメッセージ一覧を取得したのち、RANK関数を使って、やり取りした相手ごとにメッセージに順位を付けます。このとき、より新しいメッセージごとに若い順位をつけるようにします。最後に、最新のメッセージ(=順位が1位のメッセージ)を取得しつつ、userテーブルを結合します。


2021-02-28 12:11 追記

MySQL5ということはWITHもRANKも利用できないと思います。であれば以下のようなSQLになるかと思います。

SQL

1SELECT 2 s.id, 3 s.to_user_id, 4 u.name, 5 s.message, 6 s.created_at 7FROM ( 8 SELECT id, from_user_id, to_user_id, message, created_at FROM message 9 UNION ALL 10 SELECT id, to_user_id, from_user_id, message, created_at FROM message 11) AS s 12JOIN user AS u ON s.to_user_id = u.id 13WHERE from_user_id = 2 14AND NOT EXISTS ( 15 SELECT * 16 FROM ( 17 SELECT id, from_user_id, to_user_id, message, created_at FROM message 18 UNION ALL 19 SELECT id, to_user_id, from_user_id, message, created_at FROM message 20 ) AS t 21 WHERE s.to_user_id = t.to_user_id AND s.created_at < t.created_at 22)

投稿2021/02/27 13:53

編集2021/02/28 03:13
neko_the_shadow

総合スコア2349

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

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

soba_umasugi

2021/02/28 01:31

neko_the_shadow様 ありがとうございます!!! 認識はそのとおりでございます。 残念ながらMySQL5.5の為、WITH句が使えません、、、 5.5の場合、group by (userid)等で行うべきでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問