1

メッセージを受信した順に表示する受信トレイをプログラムしようとしましたが、メッセージが読まれたかどうかによって、しばらくの間は機能しているように見えましたが、そうではありませんでした。たぶん、特定の状況下でのみ機能した可能性があります..

とにかく、ここに私の質問があります。

SELECT `id`, `from_userid`, `read`, max(sent) AS sent 
FROM (`who_messages`) 
WHERE `to_userid` = '41' 
GROUP BY `from_userid` 
ORDER BY `read` ASC, `sent` DESC

問題は、メッセージが間違った順序でグループ化されていることだと思います..新しいメッセージが存在する場合、受信トレイは常に既読として表示されます。新しいメッセージの適切な時刻を取得しますが、max(sent) を選択したため、これを推測しています。

私の論理は間違っていますか?または、すべての努力の結果、「すべての派生テーブルには独自のエイリアスが必要です」という結果になったので、並べ替えてからグループ化できますか

4

4 に答える 4

4

SQL Fiddle をセットアップします - これが私が思いついた最高のものです。基本的に、サブクエリで最初に順序付けを行い、その後でグループ化します。私が入力した(限られた)テストデータでうまくいくようでした。

SELECT *
FROM (SELECT id, from_userid, is_read, sent
      FROM who_messages 
      WHERE to_userid = 41
      ORDER BY from_userid ASC, is_read ASC) m 
GROUP BY m.from_userid
ORDER BY m.is_read ASC, m.sent DESC

フィドルを参照してください: http://sqlfiddle.com/#!2/4f63d/8

于 2012-06-05T20:54:57.057 に答える
2

グループ化されたクエリで非グループ化フィールドを選択しています。グループのどのレコードが返されるかは保証されず、 のORDER BY後に処理されGROUP BYます。

これを試して:

SELECT  m.*
FROM    (
        SELECT  DISTINCT from_userid
        FROM    who_messages
        WHERE   to_userid = 41
        ) md
JOIN    who_messages m
ON      m.id = 
        (
        SELECT  mi.id
        FROM    who_message mi
        WHERE   (mi.to_userid, mi.from_userid) = (41, md.from_userid)
        ORDER BY
                mi.sent DESC, mi.id DESC
        LIMIT 1
        )

これが高速に動作するようにインデックスを作成しますwho_message (to_userid, from_userid, sent, id)

アップデート

上記のクエリは、特定のユーザーからの最後のメッセージ (既読ステータスを含む) のレコードを返します。ユーザーからの未読メッセージがあることを確認したい場合は、これを使用します。

SELECT  m.*, md.all_read
FROM    (
        SELECT  from_userid, MIN(read) AS all_read
        FROM    who_messages
        WHERE   to_userid = 41
        GROUP BY
                from_userid
        ) md
JOIN    who_messages m
ON      m.id = 
        (
        SELECT  mi.id
        FROM    who_message mi
        WHERE   (mi.to_userid, mi.from_userid) = (41, md.from_userid)
        ORDER BY
                mi.sent DESC, mi.id DESC
        LIMIT 1
        )

これを高速に動作who_message (to_userid, from_userid, read)させるには、(前のインデックスに加えて) にインデックスを作成します。

于 2012-06-05T20:32:06.357 に答える
2

Quassnoi が言ったように、GROUP BY クエリを使用し、集計関数ではない「読み取り」で注文しています。したがって、MySQL エンジンによって使用される値を特定することはできません (通常はグループの最後ですが...)

サブクエリを含まず、他の多くのパフォーマンスに適した使用法があるため、この方法でクエリを作成することをお勧めします。

SELECT
    from_userid,
    COUNT(*) AS nb_messages,
    SUM(NOT is_read) AS nb_unread_messages,
    MAX(sent) AS last_sent
FROM who_messages
WHERE to_userid = 41
GROUP BY from_userid
ORDER BY nb_unread_messages DESC, last_sent DESC;

(私は Andy Jones のフィドル スキーマを使用しました: http://sqlfiddle.com/#!2/4f63d/8
ちなみに、Andy に感謝します。このサイトは素晴らしいです!)

この助けを願っています!

于 2012-06-06T09:41:20.650 に答える
1

「メッセージを受信した順序で表示し、メッセージが読み取られたかどうかによって表示される受信トレイ...ただし、最新のメッセージであると想定されます」-読み取りはnull許容の日付/時刻列であり、メッセージは次の場所に保存されます。それらが送信される順序(新しいものは古いものよりも大きなIDを持ちます-autoid)

SELECT wm.id, wm.from_userid, (wm.read IS NULL) as unread, wm.sent
FROM (SELECT MAX(id) AS id FROM who_messages WHERE to_userid = '41' GROUP BY from_userid) sub
INNER JOIN who_messages wm ON sub.id = wm.id
ORDER BY wm.sent DESC, wm.read
于 2012-06-05T20:42:23.400 に答える