次の表がありますsession
。
sessionid | user_id | begin (timestamp)
----------+---------+-------------------
1 | A | 1234
2 | B | 4567
3 | A | 8912
4 | C | 3456
テーブルは、ユーザーのセッションに関する情報を提供します。基本的に、セッションはユーザーがログインに成功したときです。
ここで、最近ログインしたユーザーのリストを取得したいと思います。ユーザーが複数のログインを持っている場合 (この表で 2 回以上発生している場合)、最新のタイムスタンプを使用します。最新のユーザーがリストの一番上になるように、リストはログイン時間順に並べる必要があります。
次の SQL クエリを使用して、これを解決しました。
SELECT s.user_id, MAX(begin) -- MAX(begin) can be left out, results are the same
FROM session s
GROUP BY s.user_id
ORDER BY MAX(s.begin) DESC
ただし、私のアプリケーションでは、これに JPA クエリを使用することになっています。そこで、これを次の JPA クエリに変換しました。
SELECT s.user
FROM Session s
GROUP BY s.user
ORDER BY MAX(s.begin) DESC
User はセッション内のエンティティであるため、ここでは user_id ではなくユーザーを選択します。Hibernate も使用しています。このクエリを実行すると、次のエラーが発生します。
ERROR [org.hibernate.util.JDBCExceptionReporter] ERROR: column "user1_.id" must appear in the GROUP BY clause or be used in an aggregate function
Hibernate でのこの動作に関するバグの説明を見つけました。
代わりにを使用してもs.user.id
問題なく動作しますが、ID しか得られず、ユーザー オブジェクトが必要です。
最初にユーザーIDを取得してからデータベースでユーザーエンティティを見つけることで回避策を作成しましたが、これには追加のデータベース呼び出しが必要であり、1つのクエリ内で実行できることがわかっているため、パフォーマンスが悪いようです。
この問題を解決するには?
アプリケーションで SQL クエリを直接使用することは許可されていません。JPA クエリ アプローチを使用して行う必要があります。