如何在 SQLAlchemy 中的一对一关系中按混合属性对同一张表进行两次引用排序?

5 python sqlalchemy

我有一张名为Userand的表Document。该表User包含:

first_name
…
Run Code Online (Sandbox Code Playgroud)

Document 持有:

id
created_by_id
deleted_by_id
…
Run Code Online (Sandbox Code Playgroud)

我想按first_name. 因此,我创建了关系creation_userdeletion_user。外键created_by_iddeleted_by_id引用同一个表。混合属性created_by应按以下顺序排序:

first_name
…
Run Code Online (Sandbox Code Playgroud)

不幸的是,SQLAlchemy 与正确的用户不匹配,结果 SQL 查询如下所示:

id
created_by_id
deleted_by_id
…
Run Code Online (Sandbox Code Playgroud)

有没有办法使用混合属性或混合表达式(请参阅sqlalchemy 文档),以便 ORDER BY 语句解析为ORDER BY user_2.first_name ASC

sna*_*erb 0

让混合表达式指定所需的用户名生成所需的排序

@created_by.expression
def created_by(cls):
    return sql.select([User.first_name]).where(User.id == cls.created_by_id)
Run Code Online (Sandbox Code Playgroud)

尽管生成的查询添加了一个额外的子查询而不是引用别名表:

@created_by.expression
def created_by(cls):
    return sql.select([User.first_name]).where(User.id == cls.created_by_id)
Run Code Online (Sandbox Code Playgroud)

另一种方法是定义关系的顺序:

creation_user = relationship("User", foreign_keys=[created_by_id], lazy="joined", order_by="User.first_name")
Run Code Online (Sandbox Code Playgroud)

这生成了问题中指定的 SQL,并且不再需要混合属性:

SELECT documents.id AS documents_id, documents.created_by_id AS documents_created_by_id, documents.deleted_by_id AS documents_deleted_by_id, users_1.id AS users_1_id, users_1.first_name AS users_1_first_name, users_2.id AS users_2_id, users_2.first_name AS users_2_first_name 
FROM documents 
LEFT OUTER JOIN users AS users_1 ON users_1.id = documents.created_by_id 
LEFT OUTER JOIN users AS users_2 ON users_2.id = documents.deleted_by_id 
ORDER BY (SELECT users.first_name 
          FROM users 
          WHERE users.id = documents.created_by_id)
Run Code Online (Sandbox Code Playgroud)

但是,如果您想要不同的顺序,则需要覆盖加载策略 - 请参阅此答案