左外连接 sqlalchemy ORM -> 获取一个对象作为结果

问题描述 投票:0回答:1

我正在寻找复制我在 pgAdmin 中使用的 SQL 查询来连接多个表并将结果表下载到 CSV 文件中。我已经成功使用 pgAdmin 并希望使用 SQLAlchemy 获得相同的结果,因为我的应用程序通过 SQLAlchemy 与数据库交互。

在 pgAdmin 中,我使用这样的查询:

SELECT * FROM visits
LEFT JOIN patients ON visits.patient_id = patients.patient_id
LEFT JOIN [many more left joins here]
WHERE visits.visit_id = 1;

为了使用 SQLAlchemy 完成相同的任务,我尝试了以下代码:

def get_all_data_for_visit(self, visit_id: int):
    try:
        stmt = select(Visit, Patient).outerjoin(Patient, and_(Visit.patient_id == Patient.patient_id, Visit.visit_id == visit_id))
        result = self.db.execute(stmt).all()
        if result:
            for row in result:
                print(row.Patient.patient_id, row.Visit.visit_type)
            return result
        else:
            return None
    except OperationalError as e:
        self.show_error_msg()

但是,此代码返回患者对象和访问对象,这不是期望的结果。我想迭代对象并将其所有属性(例如,

row.Visit.visit_type
)打印到 CSV 中。我不能简单地迭代所有现有对象,因为有些对象可能是
None
,但我仍然希望结果(在本例中为
null
)在表中。对于我的 SQL 查询,这是可行的。使用 sqlalchemy 我得到一个 AttributeError。

我阅读了相关问题,但找不到我的具体问题的解决方案。

谢谢您的帮助!

python sql sqlalchemy
1个回答
0
投票

SQLAlchemy 的 ORM 层在连接结果中返回对象元组,因为,一般来说,程序员使用 ORM 是因为使用对象图而不是行数据的平面数组更方便。在问题中的情况下 - 将联接查询结果直接写入报告 - 使用平面数组更方便。解决方案是使用 SQLAlchemy 的核心层而不是 ORM,这将像常规 SQL 一样运行。

核心层使用表而不是 ORM 实体。鉴于 ORM 实体类存在,可以从中获取表:

patients = Patient.__table__ visits = Visit.__table__
查询语句几乎相同,只是列是通过表的 

.c

(或 
.columns
)属性而不是直接访问的:

q = stmt = ( sa.select(Patient, Visit) .outerjoin(Patient, Visit.patient_id == Patient.patient_id) .where(Visit.visit_id == visit_id) )
为了复制问题中的 SQL,我切换了投影中表的顺序,并且如 

Barmar implied 那样,将 visit_id

 过滤器从连接条件移至 
WHERE
 子句。查询可以通过会话或连接执行。

执行的结果将是一个

CursorResult 实例,您可以将其视为命名元组的可迭代对象。可以通过名称或位置访问一行中的各个列。

请注意,SQLAlchemy 将自动消除结果列中多次出现的标识符的歧义。您可以通过调用

CursorResult

.keys()
 方法来查看结果中的列名称。

© www.soinside.com 2019 - 2024. All rights reserved.