Grails/GORM/HQL:从部件中消除内部查询

Grails/GORM/HQL:从部件中消除内部查询,grails,hql,gorm,Grails,Hql,Gorm,我有一张类似于这张桌子的桌子: id user_id owner_id due_date ------+------------+-------------+-------------------------- 1 | 1 | 1 | 2011-07-26 12:28:50 2 | 1 | 1 | 2011-07-26 15:32:11 3 | 1 |

我有一张类似于这张桌子的桌子:

id     user_id      owner_id      due_date
------+------------+-------------+--------------------------
1     | 1          | 1           | 2011-07-26 12:28:50
2     | 1          | 1           | 2011-07-26 15:32:11
3     | 1          | 1           | 2011-07-27 08:11:58
4     | 2          | 1           | 2011-07-26 15:19:44
5     | 2          | 1           | 2011-07-23 12:00:50
如您所见,由FK
user\u id
标识的用户可以有多个具有不同
到期日的条目

我想获取按用户id分组的所有最新
实体

在普通MySQL中,它可能如下所示:

SELECT * FROM (
    SELECT * FROM TABLE
      WHERE owner_id = xxx
      ORDER BY due_date DESC
  ) AS sorted
GROUP BY user_id
我会首先使用ORDER BY进行选择,然后应用GROUP BY(不幸的是,多功能选择无法工作。请参见此处示例)

现在我想将其实现为HQL(使用Grails)。问题是HQL不支持FROM部件中的内部SELECT,因此以下方法不起作用:

def findMostRecentPerUser( Owner owner ) {
    def result = Table.executeQuery("""
                from Table as t1
                where t1.id in (
                    select sorted.id from (select * from Table as t2 where t2.owner_id = ${owner.id} order by t2.due_date desc) as sorted group by sorted.user_id
            )
        """)
    return result
}
另一种方法是标准,但我不知道如何以这种方式实现它


有人能给我指出正确的方向吗?非常感谢您的帮助。

为什么不将MySql排除在外,直接获取结果并使用排序工具进行排序呢。通过这种方式,无论数据库如何实现,garentee排序都是相同的

List<Table> results = query();
Collections.sort(results, YourCustomComparator.getInstance());
def findMostRecentPerUser( Owner owner ) {
    // Inner query sorts maximum due_date per user
    // Outer query fetches all Table entries with this due_date
    def result = Table.executeQuery("""
            from Table as t1
            where t1.due_date in (
                select max(t2.due_date) from Table as t2 where t2.owner = :owner group by t2.user
            )
        """,
        [ owner: owner ] )
    return result
}
List results=query();
Collections.sort(results,YourCustomComparator.getInstance());
这样做还可以减少数据库的负载,因为它会变成一个简单的查询,而不需要ORDERBY


请参阅Collections文档。

我不确定您的意图是否可行(我甚至不确定您是否应该能够使用原始SQL执行此操作)

您希望使用
Group By
语句,该语句(在我的理解中)仅在与聚合函数结合使用时才有意义,但您没有使用聚合函数。我假设您的目标是获得如下所示的数据结构:
[user\u id\u 1:[t1,t5,t2],user\u id\u 2:[t3,t4,t8]…]
(其中tX是
表中的一个实例)是否正确

如果是这种情况,我认为您只需要重新获取您关心的实例集,并自己组织它们:

def findMostRecentPerUser( Owner owner ) {
  def someDate = new Date() - 5 // 5 Days ago
  def result = [:].withDefault{[]}
  Table.withCriteria {
    eq('owner.id', owner.id)
    gt('due_date', someDate)
    order('due_date', 'desc')
  }.each{result[it.user.id] << it}
  return result
}
def FindMosterRecentPeruser(所有者){
def someDate=新日期()-5//5天前
def result=[:].withDefault{[]}
表1.1:标准{
等式('owner.id',owner.id)
gt(“到期日”,某日)
订单(‘到期日’、‘说明’)

}.每个{result[it.user.id]都应该以这种方式工作。欢迎改进

def findMostRecentPerUser( Owner owner ) {
    // Inner query sorts maximum due_date per user
    // Outer query fetches all Table entries with this due_date
    def result = Table.executeQuery("""
            from Table as t1
            where t1.due_date in (
                select max(t2.due_date) from Table as t2 where t2.owner = :owner group by t2.user
            )
        """,
        [ owner: owner ] )
    return result
}

您想返回日期集合的内容是什么?我想我很困惑。为什么需要子查询?它只是按日期排序吗?我想选择整行,即完整的
实体,以便在Grails中进一步使用。我在原始问题中已澄清了这一点。子查询是必需的,因为一个简单的
用户分组d按到期日排序
不会产生正确的结果,请参见此处,了解类似的问题描述:谢谢您的回复,Michael。由于结果集可能会变得非常大,我不想加载所有记录只是为了对它们进行排序,我更愿意在查询中处理此问题。此外,HQL查询还应该抽象数据库实现tails.您的假设是正确的,除了我只对每个用户最近的一行感兴趣这一事实。我已经尝试应用了distinct,但这基本上存在问题,因为上面的问题分组-以下代码返回了错误的行,因为distinct似乎是首先应用的。def results=Table.withCriteria{eq(“owner”,owner)projections{distinct(“user”)}order(“due_date”,“desc”)}啊,这样就可以了。嗯……我唯一能想到的另一件事就是重构:为mostRecentTable的用户添加一个字段,然后你可以加入该属性,以正确的方式限制结果(如果在创建关联表对象时要求更新用户对象,那就太糟糕了——假设您可以使用另一个可能更好的关联表进行更新)。对于严格使用您的查询,我没有任何其他想法。祝您好运!