sqlalchemy将两个表连接在一起

时间:2019-03-12 14:54:33

标签: python join sqlalchemy

我想将一个类对象映射到一个表,该表是两个表之间的联接,并且一个表中的所有列以及联接表中的仅一列被选中(映射)。

join_table = join(table1, table2, tabl1.c.description==table2.c.description)
model_table_join= select([table1, table2.c.description]).select_from(join_table).alias()

我这样做正确吗?

1 个答案:

答案 0 :(得分:1)

如果您要做的只是从JOIN中拉出一列,那么我不会为任意选择映射而烦恼。作为documentation points out

  

几乎不需要映射到任意SELECT语句的实践,尤其是如上所述的复杂语句。它必然会产生复杂的查询,而这些查询的效率通常比直接查询构造要低。这种做法在某种程度上基于SQLAlchemy的早期历史,其中mapper()构造旨在表示主要的查询接口。在现代用法中,Query对象实际上可用于构造任何SELECT语句,包括复杂的复合内容,并且应优先于“映射到可选”方法。

您只需在应用程序中选择该额外的列:

session.query(Table1Model, Table2Model.description).join(Table2Model)

或者您可以在Table1Modelassociation property上注册一个关系,该关系始终会拉出额外的列:

class Table1Model(Base):
    # ...

    _table2 = relationship('Table2Model', lazy='join')
    description = association_proxy('_table2', 'description')

当您在Table2Model.description实例上与之交互时,关联属性将管理联接行的Table1Model列。

也就是说,如果您必须坚持使用join()查询作为基础,则可以使用exclude_properties mapper argument从连接中排除额外的重复列:

join_table = join(table1, table2, table1.c.description == table2.c.description)

class JoinedTableModel(Base):
    __table__ = join_table
    __mapper_args__ = {
        'exclude_properties' : [table1.c.description]
    }

然后,新模型将使用联接中的所有列来创建具有相同名称的属性,但“ exclude_properties”中列出的属性除外。

或者您可以通过简单地给它们提供新名称来继续在模型中使用重复的列名称:

join_table = join(table1, table2, table1.c.description == table2.c.description)

class JoinedTableModel(Base):
    __table__ = join_table

    table1_description = table1.c.description

您可以通过这种方式重命名连接中的任何列,此时它们将不再与其他表中具有相同基本名称的其他列冲突。