web-dev-qa-db-ja.com

mysqlテーブルから最新の日付レコードのセットを選択する方法

さまざまなrpc呼び出しに対する応答を、次のフィールドを持つmysqlテーブルに保存しています。

Table: rpc_responses

timestamp   (date)
method      (varchar)
id          (varchar)
response    (mediumtext)

PRIMARY KEY(timestamp,method,id)

methodidの既存のすべての組み合わせに対して最新の応答を選択する最良の方法は何ですか?

  • 日付ごとに、特定のメソッド/ IDに対して1つの応答のみが可能です。

  • 特定の日付に必ずしもすべての呼び出しの組み合わせが存在するとは限りません。

  • 多数のメソッド、数千のID、および少なくとも365の異なる日付があります

サンプルデータ:

timestamp  method  id response
2009-01-10 getThud 16 "....."
2009-01-10 getFoo  12 "....."
2009-01-10 getBar  12 "....."
2009-01-11 getFoo  12 "....."
2009-01-11 getBar  16 "....."

望ましい結果:

2009-01-10 getThud 16 "....."
2009-01-10 getBar 12 "....."
2009-01-11 getFoo 12 "....."
2009-01-11 getBar 16 "....."

(私は this と同じ質問だとは思わない-最新のresponseを教えてくれない)

24
Ken

自己回答しましたが、テーブルが大きくなるにつれてそれが十分に効率的なソリューションになるかどうかはわかりません。

SELECT timestamp,method,id,response FROM rpc_responses 
INNER JOIN
(SELECT max(timestamp),method,id FROM rpc_responses GROUP BY method,id) latest
USING (timestamp,method,id);
14
Ken

このソリューションは注意して使用してください:
mysqlの将来のバージョンでの動作は保証されていません
mariadb 5.5で動作することは知られていない

結合がないので、これはクエリを実行できます。

SELECT * FROM (
    SELECT timestamp, method, id, response
    FROM rpc_responses
    WHERE 1 # some where clause here
    ORDER BY timestamp DESC
) as t1
GROUP BY method

"group by"は、メソッドの結果セットを折りたたみ、内部クエリのORDER BYタイムスタンプDESCにより、メソッドごとに1行のみ、最新の行を返します。

参考までに、PostgreSQLにはこれを行う方法が言語に組み込まれています。

SELECT DISTINCT ON (method) timestamp, method, id, response
FROM rpc_responses
WHERE 1 # some where clause here
ORDER BY method, timestamp DESC
28
velcrow

これを試して...

SELECT o1.id, o1.timestamp, o1.method, o1.response   
FROM rpc_responses o1
WHERE o1.timestamp = ( SELECT max(o2.timestamp)
                       FROM rpc_responses o2
                       WHERE o1.id = o2.id )
ORDER BY o1.timestamp, o1.method, o1.response

... Accessでも機能します!

6
versek

データセットが大きくなると、サブクエリは非常に負担が大きくなります。

これを試して:

SELECT t1.* 
FROM rpc_responses AS t1 
INNER JOIN rpc_responses AS t2 
GROUP BY t1.method, t1.id, t1.timestamp
HAVING t1.timestamp=MAX(t2.timestamp)    
ORDER BY t1.timestamp, t1.method, t1.response;
0
Simon

私はこれを使って、私のために働いた

select max(timestamp),method,id from tables where 1 group by method,id order by timestamp desc 
0
charles