2012-06-12 1 views
31

のは、私が列を持つmessagesと呼ばれるテーブルがあるとしましょう:私はあなたが実際のスレッドにドリルダウンする前に、あなたのFacebookの受信箱に見るであろうように、のみ、各ユーザからの最新メッセージを取得したいGROUP BYを使用して各グループで最新のレコードを取得する方法は?

id | from_id | to_id | subject | message | timestamp 

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

SELECT * FROM messages GROUP BY from_id 

クエリは私に、各ユーザーではなく、最新の最も古いメッセージを与えているが。

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

+0

この問題に対するより良い解決策があります[ここ](http://stackoverflow.com/questions/1313120/retrieving-the-last-レコードグループ) –

答えて

74

あなたは、各グループ(サブクエリ)の最後の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; 
+4

+1一般的な問題ですが、グループに含まれていないselectのカラムを許可するというMySQLの機能を使用してくれていないことに感謝します! – GarethD

+0

ありがとうSOOO!追加のテーブルに問題なく参加できました。そのような良いアプローチ。 – user1019144

+0

これはちょうど完璧です。 – enchance

-4

ご注文いただく必要があります。

SELECT * FROM messages GROUP BY from_id ORDER BY timestamp DESC LIMIT 1

+0

selectトップ(1)* .... – BumbleB2na

+0

@ BumbleB2na 'LIMIT 1'とは? – Li0liQ

+0

今、あなたはすべてのメッセージの最後のメッセージを受け取るでしょう、あなたはどこの条件が必要です – jcho360

1

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

MySQLでは、標準SQLにはないGROUP BY句の列を省略することができますが、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にフィルタを追加しました。クエリはそれなしで動作しますが、一般的にもっと多くのデータを返します。ネストされたクエリと外部クエリの両方に条件を記述する必要はありません(オプティマイザは自動的に条件をプッシュする必要があります)が、このように条件を繰り返すことは問題ありません。

+0

最新の標準SQLでは、 'GROUP BY'を使用し、それらが' GROUP BY 'の組み合わせに機能的に依存しているならば、 'SELECT'または' HAVING'節にそれらを含めてください。 (MySQLは当然そのようなチェックはしません) –

+0

@ypercubeこれがこの場所であるかどうかは分かりませんが、このための良いリンクはありますか?グループに含まれていない列をどのように選択するかは、グループ内の項目に依存することによって決定的になる可能性があります。しかし、例を見ることは事を明確にするのに役立つかもしれません。ありがとう – GarethD

+0

'GROUP BY pk'は簡単な例です。私の答え[ここ](http://stackoverflow.com/questions/7594865/why-does-mysql-add-a-feature-that-c​​onflicts-with-sql-standards/7596265#7596265)にリンクしています(コピーの)。 –

2

ただ、以下のコードは、質問に応じて発注されていない、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; 

それは我々が「SOURCE」を並べ替える最初の必要があるので、句「BY GROUP」がメインクエリでなければなりません

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; 

よろしく、

12

この

を試してみてください。必要なので、 "グループ化" を取得します
SELECT * FROM messages where id in (SELECT max(id) FROM messages GROUP BY from_id) order by id desc 
+3

このコードは疑問に答えるかもしれませんが、_context_を説明し、_how_を説明し、_when_を使用する方がよいでしょう。コードのみの回答は長期的には有用ではありません。 –

+0

"SELECT max(id)FROM messages GROUP BY from_id"この内部クエリは、最初にユーザー(from_id)によってレコード/メッセージをグループ化し、最大レコードIDを取得します。次に、メッセージテーブルに対して再度クエリを実行し、内部クエリ結果セットから最新のレコード/メッセージのみを取得します。 –

+0

最も簡単な解決策IMHO – Nowdeen

2

すべての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; 
+0

正直なところ、この回答は過小評価されています。これは私の自動インクリメントフィールド以外の別のフィールドでグループ化しているので、私にとってはうまくいった唯一の解決策でした。日付で最新のものを選択する必要があります。 –

+0

この回答は、Hibernate HQLと連携するのに役立ちました。 HibernateはWHEREとSELECTの後にのみサブクエリをサポートするので、他の答えはどれも動作しませんでした。この答えはサブクエリをまったく使用しないので、うまくいきました。 – Alex

関連する問題