在ORM查询中使用原始SQL

时间:2017-08-28 13:36:24

标签: python sqlalchemy

是否可以使用您自己的原始SQL编辑或覆盖ORM生成的SQL?或者ORM是否足够灵活,可以构建我能想象的任何查询?

具体来说,这就是我想要提出的问题,或许通过ORM构建起来并不困难,尽管我还没有看到任何明显的构建路径它。这是模特:

class AllocationStatus(Base):

    STATUS_RESERVED = 1
    STATUS_RELEASED = 2
    STATUS_CHOICES = (
        (STATUS_RESERVED, "Reserved"),
        (STATUS_RELEASED, "Released"),
    )

    __tablename__ = 'allocation_status'

    id = Column(Integer, primary_key=True)
    allocation_id = Column(Integer, ForeignKey('allocation.id'))
    allocation = relationship('Allocation')
    status = Column(Integer())

我的想法是,对于allocation_id的给定外键ID,我想知道allocation_status中的最新记录。

为了在原始SQL中实现这一点,以下查询是我的目标:

SELECT allocation_status.*
FROM allocation_status
LEFT JOIN allocation_status allocation_status2
    ON allocation_status.allocation_id = allocation_status2.allocation_id
    AND allocation_status.id < allocation_status2.id
WHERE allocation_status2.id IS NULL;

2 个答案:

答案 0 :(得分:3)

您可以通过首先对模型进行别名,然后将该别名作为第二个表用于外部联接来构建它。 以下假设您已经有一个绑定到工作引擎的会话:

from sqlalchemy.orm import aliased
from sqlalchemy import and_


allocation_status2 = aliased(AllocationStatus)
session.query(AllocationStatus).\
    outerjoin(allocation_status2,
              and_(AllocationStatus.allocation_id == allocation_status2.allocation_id,
                   AllocationStatus.id < allocation_status2.id)).\
    filter(allocation_status2.id.is_(None)).all()

我希望这会有所帮助。

答案 1 :(得分:2)

@Abdou的答案是正确的方法,但您也可以使用Query.from_statement()运行文本SQL:

session.query(AllocationStatus).\
    from_statement(text("""
        SELECT allocation_status.*
        FROM allocation_status
        LEFT JOIN allocation_status allocation_status2
               ON allocation_status.allocation_id = allocation_status2.allocation_id
              AND allocation_status.id < allocation_status2.id
        WHERE allocation_status2.id IS NULL;""")).\
    all()

请注意使用text()