Ответ 1
Прямая версия этого запроса выглядит так (при условии, что пары (name, version)
уникальны):
select f from FeatureList f
where f.version =
(select max(ff.version) from FeatureList ff where ff.name = f.name)
У меня есть объект Hibernate, который выглядит следующим образом (аксессоры опущены для краткости):
@Entity
@Table(name="FeatureList_Version")
@SecondaryTable(name="FeatureList",
[email protected](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;
}
Я хочу создать HQL-запрос, который извлекает самую последнюю версию FeatureList. Следующие виды запросов:
Select f.name, max(f.version) from FeatureList f group by f.name
Проблема заключается в том, что не будет заполнено поле ключа, в котором мне нужно будет содержать ключ записи с наивысшим номером версии для данного FeatureList. Если я добавлю f.key в select, это не сработает, потому что это не в группе или в агрегате, и если я поместил ее в группу, все перестанет работать, и она просто дает мне каждую версию как отдельный объект.
Итак, может ли кто-нибудь помочь?
Прямая версия этого запроса выглядит так (при условии, что пары (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 (...)
. Вам просто нужно использовать session.createNativeQuery()
в спящем режиме.
Отредактировано для работы над ответом axtavt
Как мы выяснили, это можно сделать так просто, как
select f from FeatureList f
where f.version =
(select max(ff.version) from FeatureList ff where ff.name = f.name)
Теперь попробуйте сделать то же самое, используя API-интерфейс Hibernate Criteria,
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);
Это отлично работает, но если выполнено следующее:
выглядит значительно быстрее:
FROM FeatureList ORDER BY version DESC LIMIT 1;
Мои испытания по аналогичному запросу с 700 000 записей в таблице занимают около 0.19s для прежней версии и 0.05s для последнего.
Как насчет этого,
from FeatureList fl where (fl.name, fl.version) in (
select f.name, max(f.version) from FeatureList f group by f.name)
Примечание. Попробуйте использовать createNativeQuery()
, его действительный запрос Oracle, не уверен в какой-либо другой базе данных.
Один вопрос, является ли пара, name
и version
уникальной? Если да, то это хорошо, иначе, если пара не уникальна, как вы думаете, как будет выбран ключ? Предположим, что одна из записей из исходного запроса:
f.name max(f.version)
------ --------------
Django 1.2
и предположим, что существует 3 key
, имеющих одну и ту же пару. Теперь ответьте, какой ключ должен быть присвоен этой записи? Надеюсь, вы поняли мою точку зрения.
Как насчет использования отдельного + порядка вместо группы?
select f.id, distinct(f.name), f.version from FeatureList f order by f.version desc