我为此感到疯狂。我有一个使用SQLAlchemy的Flask应用程序。我想做一个我认为非常简单的查询:
SELECT * FROM event e
LEFT JOIN event_data ed on e.id = ed.event_id
WHERE ed.datetime > '2018-12-01'
这是我的模特
class Event(db.Model):
__tablename__ = 'event'
id = db.Column(db.Integer, primary_key=True)
# ... many fields...
event_data = db.relationship("EventData", back_populates="event", lazy='joined', order_by="desc(EventData.id)")
class EventData(db.Model):
__tablename__ = 'event_data'
id = db.Column(db.Integer, primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'))
# ... many fields ...
event = db.relationship("Event", back_populates="event_data")
当我尝试
Event.query.filter(EventData.datetime>'2018-11-04')
我得到了这个SQL
SELECT every_column_from_event, every_column_from_event_data
FROM event_data, event
LEFT OUTER JOIN event_data AS event_data_1 ON event.id = event_data_1.event_id
WHERE event_data.datetime > %s
ORDER BY event_data_1.id DESC
笛卡尔积+外部联接,这需要永远运行。
我也尝试过:
Event.query.join(EventData).filter(EventData.datetime>'2018-11-04')
给出:
SELECT every_column_from_event, every_column_from_event_data
FROM event
INNER JOIN event_data ON event.id = event_data.event_id
LEFT OUTER JOIN event_data AS event_data_1 ON event.id = event_data_1.event_id
WHERE event_data.datetime > %s
ORDER BY event_data_1.id DESC
没有更多的笛卡尔积,但是有2个连接,1个INNER,1个LEFT OUTER。
如果我将加载方式更改为默认的lazy =“ select”,则会得到查询
SELECT every_column_from_event
FROM event
INNER JOIN event_data ON event.id = event_data.event_id
WHERE event_data.datetime > %s
导致N + 1选择问题的。 在我的情况下,N可能很大,所以不是一种选择。
非常感谢您的帮助。
答案 0 :(得分:1)
的确。在第二个参数中输入条件就可以了。
与
一起join(...).options(contains_eager(Event.event_data))
以防止额外的联接。
但是我仍然认为这是一种解决方法,因为条件是“ ON”子句的一部分,而不是“ WHERE”子句的一部分。无论如何,它是可行的。谢谢。
答案 1 :(得分:-1)
.join()有一个可选的第二个参数,用作on子句。因此,我相信您正在寻找的是:
Event.query.join(EventData, EventData.datetime>'2018-11-04')