HQL-запрос для объекта с максимальным значением - PullRequest
30 голосов
/ 21 декабря 2010

У меня есть объект 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;

}

Я хочу создать запрос HQL, который получает самую последнюю версию FeatureList.Работает следующий запрос:

Select f.name, max(f.version) from FeatureList f group by f.name

Беда в том, что поле ключа не заполнится, и мне нужно содержать ключ записи с наибольшим номером версии для заданного FeatureList.Если я добавлю f.key в select, он не будет работать, потому что он не входит в группу или в совокупность, и если я помещу его в группу, вся вещь перестает работать, и он просто дает мне каждую версию как отдельную сущность.

Итак, кто-нибудь может помочь?

Ответы [ 5 ]

58 голосов
/ 21 декабря 2010

Простая версия этого запроса выглядит следующим образом (при условии, что (name, version) пары уникальны):

select f from FeatureList f 
where f.version = 
     (select max(ff.version) from FeatureList ff where ff.name = f.name)
13 голосов
/ 21 декабря 2010

Я сделал сценарий здесь,


Таблица

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           

Примечание: на этот раз попробовал использовать MySQL. Работает. Я уверен, что MS SQL Server также имеет оператор IN (...). Вам просто нужно использовать session.createNativeQuery() в Hibernate.


Отредактировано для работы над ответом акставта

Как мы выяснили, это можно сделать так же просто, как,

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();
8 голосов
/ 30 января 2013

Старый вопрос, но я подумал, что я также предоставлю свой опыт здесь для будущих пользователей:

select f from FeatureList f where f.version = 
 (select max(ff.version) from FeatureList ff where ff.name = f.name);

Это прекрасно работает, но если выполняется следующее:

  • MySqlv5.5 с механизмом InnoDB
  • Вы точно знаете, сколько строк результатов вы хотите (OC подразумевает, что он / она хочет ровно 1 строку, но приведенный выше запрос будет работать для различного числа результатов)

следующее выглядит очень значительно быстрее:

FROM FeatureList ORDER BY version DESC LIMIT 1;

Мои исследования по аналогичному запросу с 700 000 записей в таблице занимают около 0,19 с для первой версии и 0,05 с для последней.

3 голосов
/ 21 декабря 2010

Как насчет этого,

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 s имеют такую ​​же пару.Теперь ответьте, какой ключ должен быть назначен этой записи?Я надеюсь, что вы поняли мою точку зрения.

0 голосов
/ 21 декабря 2010

Как насчет использования отличного + порядка по вместо группы по?

select f.id, distinct(f.name), f.version from FeatureList f order by f.version desc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...