最大値を持つエンティティのHQLクエリ
次のようなHibernateエンティティがあります(簡潔にするためにアクセサーは省略されています)。
@Entity
@Table(name="FeatureList_Version")
@SecondaryTable(name="FeatureList",
pkJoinColumns=@PrimaryKeyJoinColumn(name="FeatureList_Key"))
public class FeatureList implements Serializable {
@Id
@Column(name="FeatureList_Version_Key")
private String key;
@Column(name="Name",table="FeatureList")
private String name;
@Column(name="VERSION")
private Integer version;
}
FeatureListの最新バージョンを取得するHQLクエリを作成します。次のクエリの並べ替えは機能します。
Select f.name, max(f.version) from FeatureList f group by f.name
問題は、キーフィールドが設定されないことです。キーフィールドには、指定されたFeatureListの最大バージョン番号を持つレコードのキーを含める必要があります。 selectにf.keyを追加すると、group byまたは集計にないため機能しません。また、f.keyをgroup byに入れるとすべてが機能しなくなり、すべてのバージョンが個別のエンティティとして提供されます。
だから、誰でも助けることができますか?
このクエリの簡単なバージョンは次のようになります((name, version)
ペアは一意です):
select f from FeatureList f
where f.version =
(select max(ff.version) from FeatureList ff where ff.name = f.name)
ここでシナリオを作成しました
テーブル
_key name version
----------- -------------------- -----------
1 adeel 1
2 adeel 2
3 adeel 3
4 ahmad 1
5 ahmad 2
6 ahmad 3
7 ahmad 4
8 ansari 1
9 ansari 2
10 ansari 3
_
元のクエリを使用した結果
_>> select f.name, max(f.version) from FeatureList f group by f.name
name max(f.version)
-------------------- ------------
adeel 3
ahmad 4
ansari 3
_
希望するクエリを使用した結果
_>> select fl.* from FeatureList fl
where (fl.name, fl.version) in (select f.name, max(f.version)
from FeatureList f group by f.name);
key name max(fl.version)
----------- -------------------- -----------
3 adeel 3
7 ahmad 4
10 ansari 3
_
NB:今回はMySQLを使用して試してみました。その働き。 MS SQL ServerにはIN (...)
演算子もあると確信しています。 Hibernateでsession.createNativeQuery()
を使用するだけです。
わかったように、これは次のように簡単にできます。
_select f from FeatureList f
where f.version =
(select max(ff.version) from FeatureList ff where ff.name = f.name)
_
Hibernate Criteria API を使用して同じことを試してください。
_DetachedCriteria versions = DetachedCriteria.forClass(FeatureList.class, "f")
.setProjection( Property.forName("f.version").max())
.add(Property.forName("f.name").eqProperty("fl.name"));
session.createCriteria(FeatureList.class, "fl")
.add( Property.forName("fl.version").eq(versions) )
.list();
_
古い質問ですが、私はここで自分の経験を将来のユーザーにも提供すると思いました:
select f from FeatureList f where f.version =
(select max(ff.version) from FeatureList ff where ff.name = f.name);
これはうまく機能しますが、以下が当てはまる場合:
- InnoDBエンジンを搭載したMySql v5.5
- 必要な結果行の数は正確にわかっています(OCは1行のみが必要であることを意味しますが、上記のクエリはさまざまな数の結果に対して機能します)
以下は非常に高速です。
FROM FeatureList ORDER BY version DESC LIMIT 1;
テーブルに700,000個のレコードがある同様のクエリでの試行では、前のバージョンで約0.19秒、後者で約0.05秒かかります。
これはどう、
_from FeatureList fl where (fl.name, fl.version) in (
select f.name, max(f.version) from FeatureList f group by f.name)
_
注:有効なOracleクエリであるcreateNativeQuery()
で試してください。他のデータベースについては不明です。
1つの質問は、name
とversion
のペアは一意ですか?はいの場合は問題ありませんが、そうでない場合はペアが一意でない場合、キーがどのように選択されると思いますか?元のクエリのレコードの1つが、
_f.name max(f.version)
------ --------------
Django 1.2
_
そして、同じペアを持つ3つのkey
sがあると仮定します。では、このレコードにどのキーを割り当てる必要がありますか?あなたが私のポイントを得ていることを願っています。
Group byの代わりにdistinct + order byを使用してはどうですか?
select f.id, distinct(f.name), f.version from FeatureList f order by f.version desc