web-dev-qa-db-ja.com

GROUP BYを使用して各グループの最新のレコードを取得する方法は?

列を持つmessagesというテーブルがあるとしましょう:

id | from_id | to_id | subject | message | timestamp

実際のスレッドにドリルダウンする前に、FaceBookの受信トレイに表示されるように、各ユーザーからのみ最新のメッセージを取得します。

このクエリは、私が必要とする結果に近づいているようです:

SELECT * FROM messages GROUP BY from_id

ただし、クエリでは、各ユーザーからの最新のメッセージではなく、最も古いメッセージが表示されます。

これを理解することはできません。

38
user1019144

各グループの最後のtimestamp値(サブクエリ)を見つけて、このサブクエリをテーブルに結合する必要があります-

SELECT t1.* FROM messages t1
  JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp;
82
Devart

これを試して

SELECT * FROM messages where id in (SELECT max(id) FROM messages GROUP BY from_id ) order by id desc
18
Venu M

このクエリは、すべてのForm_idの最後のレコードを返します。

    SELECT m1.*
     FROM messages m1 LEFT JOIN messages m2
     ON (m1.Form_id = m2.Form_id AND m1.id < m2.id)
     WHERE m2.id IS NULL;
3
leyla azari

これは標準的な問題です。

MySQLでは、GROUP BY句から列を省略することができますが、標準SQLではできませんが、MySQL機能を使用する場合、一般的に確定的な結果は得られません。

SELECT *
  FROM Messages AS M
  JOIN (SELECT To_ID, From_ID, MAX(TimeStamp) AS Most_Recent
          FROM Messages
         WHERE To_ID = 12345678
         GROUP BY From_ID
       ) AS R
    ON R.To_ID = M.To_ID AND R.From_ID = M.From_ID AND R.Most_Recent = M.TimeStamp
 WHERE M.To_ID = 12345678

To_IDにフィルターを追加して、あなたが持っていると思われるものに一致させました。クエリはそれなしでも機能しますが、一般的にはより多くのデータを返します。ネストされたクエリと外部クエリの両方で条件を指定する必要はありません(オプティマイザーは条件を自動的にプッシュダウンする必要があります)が、示されているように条件を繰り返しても害はありません。

1

Devartが言ったことを補足するだけですが、以下のコードは質問に従って順序付けされていません。

SELECT t1.* FROM messages t1
  JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp;

「GROUP BY」句は、必要な「グループ化」を取得するために最初に「SOURCE」を並べ替える必要があるため、メインクエリに含まれている必要があります。

SELECT t1.* FROM messages t1
  JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages ORDER BY timestamp DESC) t2
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp GROUP BY t2.timestamp;

よろしく、

1