简体   繁体   English

如何使用SqlAlchemy通过联接构造计数聚合?

[英]How can I construct a count aggregation over a join with SqlAlchemy?

I have a table of users, a table of groups that those users may belong to, and a join table between users and groups. 我有一个用户表,一个这些用户可能属于的组表以及一个用户与组之间的联接表。

This is represented in SQLAlchemy as follows: 这在SQLAlchemy中表示如下:

class User(Base):
    __tablename__ = 'user'
    user_id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False)
    email = Column(String(250), nullable=False)
    groups = relationship('Group', secondary='user_group_pair')

class Group(Base):
    __tablename__ = 'group'
    group_id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False)
    date_created = Column(String(250), nullable=False)
    members = relationship('User', secondary='user_group_pair')

class User_Group_Pair(Base):
    __tablename__ = 'user_group_pair'
    user_group_pair_id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('user.user_id'))
    group_id = Column(Integer, ForeignKey('group.group_id'))
    user = relationship(User, backref=backref("group_assoc"))
    group = relationship(Group, backref=backref("user_assoc"))

I'm trying to solve the following simple problem: 我正在尝试解决以下简单问题:

I want to write a query that will return a list of users along with the number of groups that each of them belongs to. 我想编写一个查询,该查询将返回用户列表以及每个用户所属的组的数量。

This requires data from both User and User_Group_Pair (thus why the title of my question refers to a join), and a count aggregation grouped by user_id. 这需要来自User和User_Group_Pair的数据(因此,我的问题的标题为何指向联接),以及由user_id分组的计数汇总。

I'm not sure why this won't work: 我不确定为什么这行不通:

subq = session.query(User_Group_Pair.user_id.label('user_id'), func.count(User_Group_Pair.user_group_pair_id).label('count')).\
group_by(User_Group_Pair.user_id).order_by('count ASC').subquery()

result = session.query(User).join(subq, User.user_id == subq.user_id).all()

I get this error: 我收到此错误:

'Alias' object has no attribute 'user_id'

However, note that I have labelled User_Group_Pair.user_id with the label 'user_id'... Any thoughts? 但是,请注意,我已经将User_Group_Pair.user_id标记为“ user_id” ...有什么想法吗?

Thank you 谢谢

http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#using-subqueries http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#using-subqueries

subquery() method on Query produces a SQL expression construct representing a SELECT statement embedded within an alias. Query上的subquery()方法产生一个SQL表达式构造,该构造表示嵌入在别名中的SELECT语句。 The columns on the statement are accessible through an attribute called c. 可以通过名为c的属性访问该语句上的列。

You can use column names with .c.column_name in your query 您可以在查询中使用带有.c.column_name列名

result = session.query(User).join(subq, User.user_id == subq.c.user_id).all()

Just change subq.user_id to subq.c.user_id ( c stands for columns ) to make it work: 只需将subq.user_id更改为subq.c.user_idc代表columns )即可使其工作:

result = session.query(User).join(subq, User.user_id == subq.c.user_id).all()

But still you will get only those users which belong to at least one group, and the number of groups is not really returned in the result of the query. 但是,您仍然只会获得至少属于一个组的那些用户,并且查询结果中不会真正返回组的数量。 The query below is an approach to solve this issue: 以下查询是解决此问题的一种方法:

q = (session.query(User, func.count(Group.group_id).label("num_groups"))
     .outerjoin(Group, User.groups)
     .group_by(User.user_id)
     )
for b, num_groups in q:
    print(b, num_groups)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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