【问题标题】:SQLAlchemy join - impossible to get the accurate query [duplicate]SQLAlchemy 连接 - 无法获得准确的查询 [重复]
【发布时间】:2018-12-13 02:30:23
【问题描述】:

我对此越来越疯狂。我有一个使用 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

笛卡尔积 + OUTER JOIN,需要永远运行。

我也试过了:

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 个连接,一个 INNER,一个 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 可能非常大,所以不是一个选择。

非常感谢您的帮助。

【问题讨论】:

    标签: python sqlalchemy flask-sqlalchemy


    【解决方案1】:

    感谢GunnarIlja

    确实如此。在第二个参数中输入条件就可以了。

    一起

    join(...).options(contains_eager(Event.event_data))
    

    防止额外的加入。

    但我仍然认为这是一种解决方法,因为条件是“ON”子句的一部分,而不是“WHERE”子句的一部分。无论如何,它有效。谢谢。

    Reference which helped

    【讨论】:

      【解决方案2】:

      .join() 有一个可选的第二个参数,用作 on 子句。所以我相信你正在寻找的是:

      Event.query.join(EventData, EventData.datetime>'2018-11-04')
      

      【讨论】:

        猜你喜欢
        • 2018-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-13
        • 1970-01-01
        • 2020-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多