[英]sqlalchemy query related tables: to join or not to join (and then to loop)?
目的:
题:
将上面的步骤1和2与联接查询结合起来,然后循环遍历以按组筛选和汇总结果,效率更高吗? 还是更有效地查询步骤1的结果,然后循环查询步骤2的结果并汇总结果?
每种方法的示例如下,希望还有其他更好的方法...
带循环方法的单查询(带连接):
# query all "groups" in "category1" and all related "items"
results = session.query(Group.id, Group.name, Item.id, Item.name).\
outerjoin(Item, Group.items).\
filter(Group.category == 'category1').\
order_by(Group.id).\
all()
groups = list()
group_ids = set(results[0][0])
current_group = results[0][:2]
current_group_items = list()
for result in results:
# for each result, combine "group" with all related "items"
if result[0] in group_ids:
current_group_items.append(result[2:])
else:
groups.append(current_group + (current_group_items,))
group_ids.add(result[0])
current_group = result[:2]
current_group_items = [result[2:]]
使用循环方法的多次查询(无联接):
# query all "groups" in "category1"
groups = session.query(Group.id, Group.name).\
filter(Group.category == 'category1').\
all()
results = []
for group in groups:
# for each "group", query all related "items"
items = session.query(Item.id, Item.name).\
filter(Item.group_id == group[0]).\
all()
# append list of related "items" to "group" result
results.append(group + (items,))
供参考的示例架构:
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
class Group(Base):
__tablename__ = 'groups'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, index=True)
category = Column(String, nullable=False, index=True)
items = relationship('Sub', back_populates='group', cascade='all')
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, index=True)
group_id = Column(Integer, ForeignKey('groups.id'), nullable=False)
group = relationship('Group', back_populates='items')
还有一个使用联接的第三个选项:让SQLAlchemy渴望加载项目并为您处理分组,因为您已经在Group
和Item
之间建立了关系:
from sqlalchemy.orm import joinedload
groups = session.query(Group).\
options(joinedload(Group.items)).\
filter(Group.category == '...').\
all()
然后,您可以使用Group.items
集合访问组中的Group.items
。
一般来说,由于执行查询涉及的延迟,因此在第二个示例中, joinedload
性能要优于“ 1 + N”查询方法。 当然,这是一种概括,有时单独的查询甚至可能会获胜,但是即使在那种情况下,您仍然可以使用这些关系-默认的关系加载策略是'select'
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.