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

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

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

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

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

SQL

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

Q&A

2回答

2833閲覧

グループチャットのチャット未読一覧を取得する(mysql, SQL)

usop

総合スコア64

MySQL

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

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

SQL

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

0グッド

0クリップ

投稿2016/09/24 10:36

お世話になります。
グループチャット(既読機能つきで、スタッフとユーザでテーブルが分かれていて、多対多)のテーブルを考えています。
あるスタッフ(staff)の未読のメッセージ一覧を取得したいのですが、何時間か考えてもクエリが思い浮かびません。どのようなクエリを書けば、未読のメッセージを取り出せるでしょうか。

途中までのクエリ(テーブルの結合のみ。条件が思い浮かばない)

sql

1select * from chat as c inner join chat_group as cg on c.chat_group_id = cg.id left join chat_read cr on c.id = cr.chat_id 2
テーブル構造 user: id, name staff: id, name chat_group: id, name chat: id, chat_group_id, user_id, staff_id, comment chat_read: id, chat_id, user_id, staff_id
データ例 user: 1, hoge_user 2, foo_user staff: 1, hoge_staff 2, foo_staff chat_group: 1, test_group chat: 1, 1, null, 1, "hello hoge_staff" 2, 1, 1, null, "hello hoge_user" chat_read: (自分で投稿したコメントは既読として登録されない) 1, 1, null, 1 2, 2, 1, null 3, 1, null, 2 <- 既読しかしないfoo_staff 4, 2, null, 2

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

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

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

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

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

guest

回答2

0

テーブル結合まではある程度いけてると思うので、後一息かとは思います。

以下ケースごとの例を記載してみるので、どう修正すべきか考えてみてください。

#あるstaffのidが事前に分かる場合
この場合は結合テーブルは質問者さんのやり方でも問題ありません。
ただ結合条件を一部変更する必要があります。

以下はfoo_staff(staff_id = 2)の既読メッセージを取得するクエリです。
(※今回の質問の参考になるよう一部非効率なやり方をしてます)

SQL

1SELECT 2 c.* 3, cg.* 4, cr.* 5FROM 6 chat as c 7 INNER JOIN chat_group as cg 8 ON c.chat_group_id = cg.id 9 LEFT JOIN chat_read as cr 10 ON c.id = cr.chat_id 11 AND cr.staff_id = 2 -- 「foo_staff」のidを指定 12WHERE 13 cr.id IS NOT NULL -- chat_readのid列がNULLか否かでデータ有無を判断できる。

また結合部からchat_readを除き、
下記のようにすることで同じようなことが可能です。
(可読性的にはこちらの方が良さ気か)
同じく既読データを取得するサンプルです。

SQL

1SELECT 2 c.* 3, cg.* 4FROM 5 chat as c 6 INNER JOIN chat_group as cg 7 ON c.chat_group_id = cg.id 8WHERE 9 -- 下記は該当レコードある場合に条件成立 10 -- レコードがない場合に条件成立する構文に「NOT EXISTS」もある 11 EXISTS( 12 -- foo_staffの既読情報を取得するクエリ 13 SELECT 14 * 15 FROM 16 chat_read as cr 17 WHERE 18 cr.chat_id = c.id 19 AND cr.staff_id = 2 20 )

#あるstaffの名前だけが事前に分かる場合
この場合はstaffテーブルも検索対象に含める必要があります。

その場合の検索方法の例を記載します。
以下は同じくfoo_staffのデータを検索してます。

SQL

1SELECT 2 c.* 3, cg.* 4, cr.* 5FROM 6 chat as c 7 INNER JOIN chat_group as cg 8 ON c.chat_group_id = cg.id 9 LEFT JOIN ( 10 SELECT 11 cr.* 12 FROM 13 chat_read as cr 14 INNER JOIN staff as s 15 ON cr.staff_id = s.id 16 WHERE 17 s.name = 'foo_staff' 18 ) as cr 19 ON c.id = cr.chat_id 20WHERE 21 cr.id IS NOT NULL -- chat_readのid列がNULLか否かでデータ有無を判断できる。

EXISTS版を投下し忘れてたので投下。

SQL

1SELECT 2 c.* 3, cg.* 4FROM 5 chat as c 6 INNER JOIN chat_group as cg 7 ON c.chat_group_id = cg.id 8WHERE 9 -- 下記は該当レコードある場合に条件成立 10 -- レコードがない場合に条件成立する構文に「NOT EXISTS」もある 11 EXISTS( 12 -- foo_staffの既読情報を取得するクエリ 13 SELECT 14 * 15 FROM 16 chat_read as cr 17 INNER JOIN staff as s 18 ON cr.staff_id = s.id 19 WHERE 20 cr.chat_id = c.id 21 AND s.name = 'foo_staff' 22 )

#最後に
上記を参考に条件部や、クエリを再考してみてください。

いずれにしろ後一押しですので、頑張って挑戦してみてください。
またわからない点あればコメントなどでは回答受け付けます。

投稿2016/09/24 13:06

編集2016/09/24 13:37
Panzer_vor

総合スコア1636

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

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

0

select * from chat where id not in ( select chat_id from chat_read where staff_id = 2);
とりあえず解決 というところだとこれでどうでしょうか?
例) staff_id が2の未読の場合

投稿2016/09/24 11:39

編集2016/09/24 11:40
shingoatail

総合スコア106

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問