
[英]SQLAlchemy: Counting and ordering by multiple relationships to the same table
[英]SQLAlchemy: Counting multiple relationships - best way?
想象一下以下(示例)数据模型:
class Organization(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
friendly_name = db.Column(db.Text, nullable=False)
users = db.relationship('Users', back_populates='organizations')
groups = db.relationship('Groups', back_populates='organizations')
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
organization_id = db.Column(db.Integer, db.ForeignKey('organizations.id'))
organizations = relationship("Organization", back_populates="users")
class Group(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
organization_id = db.Column(db.Integer, db.ForeignKey('organizations.id'))
organizations = relationship("Organization", back_populates="groups")
(所以基本上一个组织有用户和组的关系)
我们想要的是检索用户和组的计数。 结果应类似于以下内容:
ID | 友好名称 | users_count | 组数 |
---|---|---|---|
1 | o1 | 33 | 3 |
2 | o2 | 12 | 2 |
3 | o3 | 1 | 0 |
这可以通过类似的查询来实现
query = db.session.query(
Organization.friendly_name,
func.count(User.id.distinct()).label('users_count'),
func.count(Group.id.distinct()).label('groups_count'),
) \
.outerjoin(User, Organization.users) \
.outerjoin(Group, Organization.groups) \
.group_by(Organization.id)
这似乎有点矫枉过正。 第一种直观的方法类似于
query = db.session.query(
Organization.friendly_name,
func.count(distinct(Organization.users)).label('users_count'),
func.count(distinct(Organization.groups).label('groups_count'),
)# with or without outerjoins
这是行不通的(注意:有一种关系会起作用)。
a) 在这种情况下, User.id.distinct()
和distinct(Organization.users)
有什么区别?
b)在 SQLAlchemy 中获得 Object 具有的每个关系的计数的最佳/最佳性能/推荐方式是什么?
奖励) :如果代替Organization.friendly_name
将选择整个 Model ( ...query(Organization, func....)
) SQLAlchemy 返回一个格式为 t(Organization, users_count, groups_count) 的元组作为结果。 有没有办法只返回带有两个计数作为附加字段的组织? (如 SQL 那样)
你可以试试 window function:
query = db.session.query(
Organization.friendly_name,
func.count().over(partition_by=(User.id, Organization.id)).label('users_count')
func.count().over(partition_by=(Group.id, Organization.id)).label('groups_count')
) \
.outerjoin(User, Organization.users) \
.outerjoin(Group, Organization.groups) \
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.