繁体   English   中英

SQLAlchemy:计算多个关系 - 最好的方法?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM