【问题标题】:SQLAlchemy JOIN vs Adjacency ListSQLAlchemy JOIN 与邻接列表
【发布时间】:2015-11-24 15:38:08
【问题描述】:

考虑以下模型:

class A(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    bs = db.relationship('B', backref='A')

class B(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    cs = db.relationship('C', backref='A')

class C(db.Model):
    id = db.Column(db.Integer, primary_key=True)

假设我想访问给定对象 A 的 C id。这是正确(也是最快)的方法吗?还是我应该进行 JOIN 查询或其他 SQL 魔术?

a = A.query.get(1)
c_ids = [c.id for b in a.bs for c in b.cs]

【问题讨论】:

    标签: python sql join sqlalchemy


    【解决方案1】:

    * EDIT * 在查询中更改每个 A 的 C!

    您可以创建一个简单的查询来解决您的问题,如下所示:

    q = session.query(C).join(B).join(A)
    c_list = q.all()
    

    c_list 将包含匹配连接条件的每个对象。 如果你想查看生成的查询,很简单:

    print(str(q))
    

    选择 c_table.c_id AS c_table_c_id, c_table.id AS c_table_id FROM c_table 加入 b_table ON b_table.id = c_table.c_id 加入 a_table ON a_table.id = b_table.a_id

    * 编辑 * 这种方法比迭代 python 对象更有效:你只有一个由数据库解析的查询,如果你迭代你的对象 SQLAlchemy 可能需要触发一些触发器来加载数据库读取的剩余对象loading relationships .

    接下来是我用来复制您的案例的脚本:

    from sqlalchemy import Column, create_engine, ForeignKey
    from sqlalchemy.orm import relationship, sessionmaker
    from sqlalchemy.types import Integer
    from sqlalchemy.ext.declarative import declarative_base
    
    model = declarative_base()
    
    class A(model):
        __tablename__ = 'a_table'
        id = Column(Integer, primary_key=True)
        bs = relationship('B', backref='A')
    
    class B(model):
        __tablename__ = 'b_table'
        a_id = Column(Integer, ForeignKey('a_table.id'))
        id = Column(Integer, primary_key=True)
        cs = relationship('C', backref='B')
    
    class C(model):
        __tablename__ = 'c_table'
        c_id = Column(Integer, ForeignKey('b_table.id'))
        id = Column(Integer, primary_key=True)
    
    
    engine = create_engine('postgresql+psycopg2://playground:playground@localhost:5432/playground')
    session_factory = sessionmaker(bind=engine)
    session = session_factory()
    
    model.metadata.create_all(engine)
    a = A()
    b = B(A=a)
    c = C(B=b)
    session.add(a)
    session.commit()
    
    q = session.query(C).filter(C.id == 1)
    c = q.first()
    print(c.B.A.id)
    
    q = session.query(A).filter(A.id == 1)
    a = q.first()
    c_id = [c.id for a in a.bs for c in b.cs]
    
    q = session.query(C).join(B).join(A)
    c_list = q.all()
    
    print(str(q))
    

    【讨论】:

    • 这将选择 A id "SELECT a_table.id AS a_table_id" 而不是 C id。
    猜你喜欢
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    相关资源
    最近更新 更多