2016-02-24 3 views
5

これはかなり一般的なケースですが、私が何か間違っているかどうかはわかりません。サブクエリなしの最新データグループ

TABLE POSTS [ ID, USER_ID, TOPIC_ID, TIME ] 

私はtopic_id '1'

SELECT p.* 
FROM 
    posts p, 
    (
    SELECT user_id, max(time) mtime 
    FROM  posts 
    WHERE topic_id = 1 
    GROUP BY user_id 
) pm 
WHERE 
    p.user_id = pm.user_id AND 
    p.time = pm.mtime 

これは正しいです上の各ユーザーによってのみ、最後のポストを取得したいですか?サブクエリなしでこれを行う方法はありますか?

スプリングデータクエリでこのデータを取得するオプションはありますか?これはJDBC /ストアドプロシージャのみのものですか?

+3

これは正しいですが、常に明示的なJOIN構文を使用してください。 – Strawberry

+1

ああ、私はあまりにも早く話しました。サブクエリのSELECTにuser_idを含める必要があります。この場合GROUP BYにtopic_idを含める必要があります(ただし、この場合は厳密には必要ありません) – Strawberry

+0

ドメインから「投稿」への翻訳がうまくいかず、 "topic_id"の代わりに "SELECT user_id、max(time)"である必要があります - 編集済み – qzshard

答えて

1

ジョイン使って、サブクエリを使用してせずに、各ユーザーの最新記事を取得することができます。

SELECT p.* 
FROM posts p 
LEFT OUTER JOIN posts t 
ON(p.user_id = t.user_id and p.time < t.time and t.topic_id = 1) 
WHERE p.topic_id = 1 and t.topic_id is null 
+0

これはかなり面白いです。この "トリック"をまだ見ていない。しかし、トピック '1'ではなく、すべてのユーザーが最後に投稿したトピックを取得します。結果をフィルタリングする方法はありますか? – qzshard

+0

@qzshardもちろん、ON句の中で答えを更新しました。もしあなたが助けてくれれば、upvote(^)と承認(V)に感謝します – sagi

+0

古い学校。良いですが、この方法はスケールが良くないことに注意してください。(OPの独自のソリューションとは異なります) – Strawberry

0

サブクエリなしで行うには、HAVINGを使用します。

SELECT user_id, topic_id, time 
FROM  posts 
WHERE topic_id = 1 
GROUP BY user_id 
HAVING time = max(time) 
+0

'HAVING time = ..'はこれが 'Mysql'で許可されています –

+0

試したことはありませんが、私はそれを想像しています: https: //dev.mysql.com/doc/refman/5.0/en/group-by-handling.html – user1717259

+0

は動作しません.1行のコンテキストに "having"を使用することはできません。 – qzshard

1

はここsub-queryを回避する方法を確認していないが、これを行うための別の方法は

になります
SELECT p.* 
FROM posts p 
WHERE p.time = (SELECT Max(time) mtime 
       FROM posts pm 
       WHERE pm.topic_id = 1 
         AND p.user_id = pm.user_id) 

ウィンドウ機能Row_numberは、残念なことにこのような場合に役に立ちますMysqlはサポートしていません

+0

ありがとう、これは私が他の質問で見た別の方法です。しかし、パフォーマンスの点では、これは非常に強いクエリではありません(オリジナルと比較して)? – qzshard

+0

@ qzshard-あなたはあなたのリアルタイムデータでそれをテストすることができます –

0

サブクエリを避けるもう1つの解決策は、最新の情報を取得するフィールドごとに時間の降順でsubstring_indexを使用し、次にSUBSTRING_INDEXを使用して最初のエントリを取得することですSUBSTRING_INDEXによって返されます。

SELECT user_id, 
    SUBSTRING_INDEX(GROUP_CONCAT(`id` ORDER BY `time` DESC), ',', 1), 
    SUBSTRING_INDEX(GROUP_CONCAT(`topic_id` ORDER BY `time` DESC), ',', 1), 
    SUBSTRING_INDEX(GROUP_CONCAT(`time` ORDER BY `time` DESC), ',', 1) 
FROM posts 
WHERE topic_id = 1 
GROUP BY user_id 
関連する問題