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
如您所见,由FKuser\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的用户添加一个字段,然后你可以加入该属性,以正确的方式限制结果(如果在创建关联表对象时要求更新用户对象,那就太糟糕了——假设您可以使用另一个可能更好的关联表进行更新)。对于严格使用您的查询,我没有任何其他想法。祝您好运!