3

ユーザー間の簡単な内部メッセージング システムが必要です。

私のテーブル:

+--------------+         +---------------------+
|   messages   |         |        users        |
+----+---------+         +---------------------+
| id | message |         | id | username | ... 
+----+---------+         +---------------------+

+------------------------------------------------------------------------------+
|                                 users_messages                               |
+------------------------------------------------------------------------------+
| id | from_usr_id | to_usr_id | msg_id | thread_id | read | sent_at | read_at |
+------------------------------------------------------------------------------+

INT 'thread_id'メッセージをグループ化するために使用される会話スレッドを表します。

BOOLEAN 'read'ユーザーがメッセージを開いた/表示したかどうかを表します。

メッセージを でグループ化し'thread_id'、並べ替えて'sent_at'、ユーザーに最新のメッセージをスレッドごとに表示できるようにします。各スレッドのメッセージもカウントしたいと思います。

特定のユーザーIDに対して次のようなものを取得したい:

+----------------------------------------------------------------------------
| last_messages_by_conversation
+----------------------------------------------------------------------------
| message | from_username | sent_at | count_thread_msgs | count_unread_msg |
+----------------------------------------------------------------------------

TEXT 'message'は、特定の最新のメッセージです。'thread_id'

VARCHAR 'from_username'およびDATETIME 'sent_at'最新のメッセージに関連しています。

INT 'count_thread_msgs'およびINT 'count_unread_msg'スレッドに関連し、スレッド内のメッセージの総数と未読メッセージの数を表します。

各行はスレッド/会話 ( でグループ化) を表し、その特定のスレッド'thread_id'の最後のメッセージ ( でソート) を示します。'sent_at'

4

5 に答える 5

5

groupwise maximumを探しています。これは、最初に でusers_messagesテーブルをグループ化してthread_idを選択MAX(sent_at)し、次に結果をusers_messagesテーブルに結合して、その最大レコードの他のフィールドを見つけることで見つけることができます。

NATURAL JOINここで非常に便利なショートカットだと思います:

SELECT   messages.message,
         users.username AS from_username,
         t.sent_at,
         t.count_thread_msgs,
         t.count_unread_msg
FROM     users_messages NATURAL JOIN (
  SELECT   thread_id,
           to_usr_id,
           MAX(sent_at)  AS sent_at,
           COUNT(*)      AS count_thread_msgs,
           SUM(NOT read) AS count_unread_msg
  FROM     users_messages
  WHERE    to_usr_id = ?
  GROUP BY thread_id
) t JOIN messages ON messages.id = users_messages.msg_id
    JOIN users    ON users.id    = users_messages.from_usr_id
于 2012-09-02T15:48:10.677 に答える
2

この解決策を試すことができます:

SELECT   c.message,
         d.username AS from_username,
         b.sent_at,
         a.count_thread_msgs,
         a.count_unread_msg
FROM     (
         SELECT   MAX(id)  AS maxid,
                  COUNT(*) AS count_thread_msgs,
                  COUNT(CASE WHEN `read` = 0 AND <uid> = to_usr_id THEN 1 END) AS count_unread_msg
         FROM     users_messages
         WHERE    <uid> IN (from_usr_id, to_usr_id)
         GROUP BY thread_id
         ) a
JOIN     users_messages b ON a.maxid       = b.id
JOIN     messages c       ON b.msg_id      = c.id
JOIN     users d          ON b.from_usr_id = d.id
ORDER BY b.sent_at DESC

これにより、ユーザーが開始した、またはユーザーが参加している各スレッドの最新のメッセージが取得されます<uid>

id最新のメッセージは、各 thread_idの最大値に基づいています。

このソリューションでは、次のことを前提としています。

  • idinusers_messagesは、新しい行ごとに一意の自動インクリメント int です。
  • 各スレッドには、2 人以上のユーザー間の通信が含まれることはありません。

スレッドに 3 人以上のユーザーが含まれる可能性がある場合は、正確なカウント集計を取得するために、クエリを少し調整する必要があります。

于 2012-09-03T02:02:17.317 に答える
2
SELECT 
      users.id,
      users.username,
      user_messages.thread_id,
      user_messages.unread ,
      messages.message 
FROM users
LEFT JOIN (SELECT 
                 from_usr_id , 
                 msg_id,
                 count(thread_id)) as thread_id,
                 count(read_at) as  unread  
          FROM user_messages)as user_messages on user_messages.from_usr_id = users.id
LEFT JOIN messages on messages.id = user_messages.msg_id
于 2012-08-31T13:25:39.107 に答える
1

これを試して、私に知らせて$$くださいuser ID..

select u.username,msg.message,m.sent_at,

(select count(*) from user_message where read=0 and to_usr_id=$$) as count_thread_msgs,

(select count(*) from user_message where to_usr_id= $$) as count_unread_msg

from users as u join user_messages as m

on u.id=m.id where u.id=$$ 

join messages as msg on msg.id=m.id

group by u.id;`
于 2012-08-31T13:18:02.533 に答える
0

このクエリを試してください -

SELECT
  m.message,
  u.username from_username,
  um1.sent_at,
  um2.count_thread_msgs,
  um2.count_unread_msg
FROM users_messages um1
  JOIN (
       SELECT
         thread_id,
          MAX(sent_at) sent_at,
          COUNT(*) count_thread_msgs,
          COUNT(IF(`read` = 1, `read`, NULL)) count_unread_msg
        FROM users_messages GROUP BY thread_id) um2
    ON um1.thread_id = um2.thread_id AND um1.sent_at = um2.sent_at
JOIN messages m
  ON m.id = um1.msg_id
JOIN users u
  ON u.id = um1.from_usr_id
-- WHERE u.id = 100 -- specify user id here

ご質問への回答:

  1. 前回の日時について: クエリを少し変更しました。新しいクエリを試してみてください。
  2. 特定のユーザーについて: WHERE 条件を追加してユーザーをフィルター処理します - ...WHERE u.id = 100
  3. messages多くのレコードについて: 別のテーブル (および)を結合usersし、同じ を持つ複数のレコードが存在する可能性があるためですthread_id。これを回避するには、thread_idフィールドごとに結果セットをグループ化し、集計関数を使用して単一の結果を取得する必要があります。たとえば、GROUP_CONCAT 関数を使用します。
于 2012-09-05T13:43:28.203 に答える