2017-05-08 79 views
1

我有兩個類,Event和Booking。一個事件可以容納很多預訂。如何定義混合表達式?

class Event(Base): 
    __tablename__ = 'event' 
    id = Column(Integer, primary_key=True) 
    space = Column(Integer) 

class Booking(Base): 
    __tablename_ = 'booking' 
    id = Column(Integer, primary_key=True) 
    event_id = Column(Integer, ForeignKey('event.id')) 
    event = relationship('Event', backref=backref('bookings')) 

現在我要計算的佔有率,並決定去Event類的混合屬性,像這樣:

@hybrid_property 
def occupancy(self): 
    return float(len(self.bookings))/float(self.space) 

這工作正常,在某些情況下,但是當我想成爲能過濾的佔用,這樣的:

session.query(Event).filter(Event.occupany > 0.5) 

這樣做,我得到這個錯誤:

TypeError: object of type 'InstrumentedAttribute' has no len() 

於是我意識到我可能需要一個混合的表達,並與上前:

@occupancy.expression 
def occupancy(cls): 
    return func.count(select([Booking.id]).where(cls.id == Booking.event_id).label('occupancy'))/cls.space 

然而,這導致MySQL錯誤:

sqlalchemy.exc.ProgrammingError: (_mysql_exceptions.ProgrammingError) 
(1111, 'Invalid use of group function') [SQL: u'SELECT event.id AS 
event_id FROM event \nWHERE count((SELECT booking.id \nFROM booking 
\nWHERE event.id = booking.event_id))/event.space > %s'] 
[parameters: (0.5,)] 

我怎樣才能構建雜體現在哪裏?還是有更好的方法來實現我想要的?

+0

在子查詢中計數,而不是在封閉查詢中:'select([func.count(Booking.id)])。where(...)...'。 –

+0

是的!您的評論是實際的答案。謝謝。如果你把它寫成真實的答案,我可以接受它。 –

回答

1

計數應在scalar subquery內完成。當前查詢嘗試將count()函數應用於封閉查詢的WHERE子句中的子查詢的結果集,而該查詢的另一方面沒有分組,因此您會收到錯誤 - 更不用說集合函數作爲謂詞屬於HAVING子句。只需移動呼叫:

@occupancy.expression 
def occupancy(cls): 
    stmt = select([func.count(Booking.id)]).\ 
     where(cls.id == Booking.event_id).\ 
     label('occupancy') 
    return stmt/cls.space