【发布时间】:2018-08-21 23:18:17
【问题描述】:
目标:
- 从一个表(称为“组”)中检索查询结果列表。
- 从相关表(称为“项目”)中检索结果列表。步骤 1 中的每个结果都有一个结果列表。
- 将第 2 步中的“项目”列表与第 1 步中相应的“组”结果组合成一个元组,该元组同时包含“组”数据和所有相关“项目”数据的列表。
问题:
将上面的第 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')
【问题讨论】:
-
请注意,您的第一种方法似乎错误地假设属于单个组的行在结果中彼此跟随。订单无法保证,并且可能会随 DBMS 的意愿而改变。
-
我编辑了第一个方法代码示例以包含一个
order_by,我认为它应该可以解决该特定问题,但是您使用joinedload的答案是我正在寻找的更好的方法。虽然,我已经阅读了Relationship Loading Techniques,但您对默认关系加载策略的评论终于让我点击了。谢谢。 -
是的,order by 解决了那个特定的 nit :)
标签: python sqlalchemy