简体   繁体   English

使用HQL和MySQL如何在组之前订购结果集,以便选择正确的记录?

[英]Using HQL with MySQL how can I order the result set before the group by so the right record is picked?

Is there any way to write a greatest-n-per-group query in HQL (or potentially with Hibernate Criteria) in a single query? 有没有办法在单个查询中用HQL(或可能使用Hibernate Criteria)编写最大的每组查询?

I'm struggling with a problem that's similar to this: 我正在努力解决与此类似的问题:

Schema: 架构:

  • Book has a publication_date 本书有一个publication_date
  • Book has an Author 本书有作者
  • Author has a Publisher 作者有一个发布者

I have a Publisher in hand, as well as a search date. 我手头有一个发布者,还有一个搜索日期。 For all of that Publisher's Authors, I want to find the book that they published most recently before the search date. 对于所有发布者的作者,我想找到他们在搜索日期之前最近发布的书。

I've been trying to get this working (and have looked at many of the other questions under hibernate as well as greatest-n-per-group ) but haven't found any examples that work. 我一直在努力让这个工作(并且已经看了很多其他问题在hibernate下以及最好的每组n )但是没有找到任何有效的例子。

In straight MySQL, I'm able to use a subselect to get this: 在MySQL中,我可以使用子选择来获取:

select * from
(select
        a.id author_id,
        b.id book_id,
        b.publication_date publication_date
   from book b
   join author a on a.id = b.author_id
   join publisher p on p.id = a.publisher_id
  where
    b.publication_date <= '2011-07-01'
    and p.id = 2
order by b.publication_date desc) as t
 group by
    t.author_id

This forces the order by to happen first in the subquery, then the group by happens afterwards and picks the most recently published book as the first item to group by. 这会强制订单在子查询中首先发生,然后按组发生,然后选择最近发布的图书作为要分组的第一个项目。 I get the author ID paired with the book ID and publication date. 我将作者ID与书籍ID和出版日期配对。 (I know this isn't a particularly efficient way to do it in SQL, this is just an example of one way to do it in native SQL that's easy to understand). (我知道在SQL中这不是一种特别有效的方法,这只是一种在本机SQL中实现它的方法的一个例子,这很容易理解)。

In hibernate, I've been unable to construct a subquery that emulates this. 在hibernate中,我无法构造一个模拟它的子查询。 I also haven't had any luck with trying to use a having clause like this, it returns zero results. 尝试使用像这样的having子句我也没有运气,它返回零结果。 If I remove the having clause, it returns the first book in the database (based on it's ID) as the group by happens before the order by: 如果我删除了having子句,它将返回数据库中的第一本书(基于它的ID)作为组在订单之前发生:

Book.executeQuery("""
        select b.author, b
        from Book b 
        where b.publicationDate <= :date
        and b.author.publisher = :publisher
        group by b.author
        having max(b.publicationDate) = b.publicationDate
        order by py.division.id
""", [date: date, publisher: publisher])

Is there any way to get hibernate to do what I want without having to spin through objects in memory or dive back down to raw SQL? 有没有办法让hibernate做我想做的事情,而不必旋转内存中的对象或潜入原始SQL?

This is against a MySQL database and using Hibernate through Grails if it matters. 如果重要的话,这是针对MySQL数据库并通过Grails使用Hibernate。

For that, you need a SQL window function . 为此,您需要一个SQL窗口函数 There is no way to do it in Hibernate/HQL, HQL doesn't support window functions. 在Hibernate / HQL中无法做到这一点,HQL不支持窗口函数。

greatest-n-per-group tag has the correct answers. greatest-n-per-group tag标签有正确的答案。 For instance, this approach is pretty readable, though not always optimal. 例如, 这种方法非常易读,但并不总是最佳的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM