使用Grails避免HQL中的子查询

使用Grails避免HQL中的子查询,grails,hql,gorm,Grails,Hql,Gorm,我有两个目标,一个房间类型和一个预订。它们是: class Room { String description int quantity } class Reservation { String who Room room } 我想查询所有房间以及每种类型的可用房间数。在SQL中,这符合我的要求: select id, quantity, occupied, quantity-coalesce(occupied, 0) as available from room left

我有两个目标,一个房间类型和一个预订。它们是:

class Room {
  String description
  int quantity
}

class Reservation {
  String who
  Room room
}
我想查询所有房间以及每种类型的可用房间数。在SQL中,这符合我的要求:

select id, quantity, occupied, quantity-coalesce(occupied, 0) as available
from room left join(select room_id, count(room_id) as occupied from reservation) 
on id = room_id;
我没有任何进展试图解决如何使用HQL实现这一点


如果有任何提示,我将不胜感激,因为我似乎在HQL或GORM中缺少了一些非常基本的东西。

我不确定如何在HQL中用子查询描述左连接。在任何情况下,如果HQL表达能力不够,您也可以在grails中轻松执行原始SQL:

在您的服务中,注入数据源并创建groovy.sql.sql实例

def dataSource

[...]    

def sql= new Sql(dataSource)
sql.eachRow("...."){row->
    [...]
}
我知道当你问问题时,人们试图以他们的思维方式来支持你,而不是回答你的问题或闭嘴,这是非常令人讨厌的,但在我看来,这个查询非常复杂,我会在我的数据结构中为这个数字创建一个概念,可能是一个与房间相关联的可用性表,这样不仅可以计算数量,还可以计算占用的价值

这不是每次需要时都计算它


只要我的$0.02,如果它烦扰您,请忽略它。

这里的问题是您试图表示非域类的字段,如
可用
占用
。试图让HQL\GORM这样做可能有点令人沮丧,但并非不可能。我想你有几个选择

1.构建您的域类,使其更易于使用。您的房间可能需要通过映射表了解其预订情况,或者,可能需要编写您想要的代码,然后调整设计。

比如说。也许你希望你的代码看起来像这样

RoomReservation.queryAllByRoomAndDateBetween(room, arrivalDate, departureDate);  
    class RoomReservation{
        ...
        def queryAllByRoomAndDateBetween(def room, Date arrivalDate, Date departureDate){
           return RoomReservation.withCriteria {
             eq('room', room)
             and {
               between('departureDate', arrivalDate, departureDate)
             }
        }
    }
然后你会像这样实现它

RoomReservation.queryAllByRoomAndDateBetween(room, arrivalDate, departureDate);  
    class RoomReservation{
        ...
        def queryAllByRoomAndDateBetween(def room, Date arrivalDate, Date departureDate){
           return RoomReservation.withCriteria {
             eq('room', room)
             and {
               between('departureDate', arrivalDate, departureDate)
             }
        }
    }
2)我的第二个想法是可以将数据库用于它的用途。有时,在代码中使用sql是最有效的方法只需适度地进行查询,并保持集中化和单元测试。我不建议您使用这种方法,因为您的查询没有那么复杂,但它是一种选择。我将存储过程用于诸如“仪表板视图”之类的查询数百万对象以获取摘要数据的功能

class Room{
    ...
  def queryReservations(){
      def sql = new Sql(dataSoruce);
      return sql.call("{call GetReservations(?)}", [this.id]) //<-- stored procedure.
  }
}
教室{
...
def queryReservations(){
def sql=新sql(dataSoruce);
返回sql.call(“{call GetReservations(?)},[this.id])//