Python SQLAlchemy group_by()简单链接表所需的求和帮助

Python SQLAlchemy group_by()简单链接表所需的求和帮助,python,sqlalchemy,flask-sqlalchemy,Python,Sqlalchemy,Flask Sqlalchemy,我已经在类似的主题上四处寻找帮助,但是没有找到解决我的问题的正确方法,这个问题涉及SQLAlchemy/Flask SQLAlchemy 情况是这样的:我有3个表处理彩票数据。表如下:Araffles表: class RaffleModel(db.Model): __tablename__ = 'raffles' id = db.Column(db.Integer, primary_key=True) # relationship to users user_

我已经在类似的主题上四处寻找帮助,但是没有找到解决我的问题的正确方法,这个问题涉及SQLAlchemy/Flask SQLAlchemy

情况是这样的:我有3个表处理彩票数据。表如下:A
raffles
表:

class RaffleModel(db.Model):
    __tablename__ = 'raffles'

    id = db.Column(db.Integer, primary_key=True)

    # relationship to users
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    user = db.relationship("UserModel", backref="raffles")

    # relationship to ticket_md
    ticket_md_id = db.Column(db.Integer, db.ForeignKey('ticket_mds.id'))
    ticket_md = db.relationship("TicketMetaDataModel", backref="raffles")

    def __init__(self, user, ticket_md):
        self.user = user
        self.ticket_md = ticket_md
class UserModel(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(25))
    last_name = db.Column(db.String(25))
    won = db.Column(db.Boolean, default=False, nullable=False)

    # has backref via user.raffles

    def __init__(self, first_name, last_name, won):
        self.first_name = first_name
        self.last_name = last_name
        self.won = won
class TicketMetaDataModel(db.Model):
    __tablename__ = 'ticket_mds'

    id = db.Column(db.Integer, primary_key=True)
    raffle_type = db.Column(db.String(20))
    description = db.Column(db.String(200))
    modifier = db.Column(db.Integer)

    # has backref via ticket_md.raffles

    def __init__(self, raffle_type, description, modifier):
        self.raffle_type = raffle_type
        self.description = description
        self.modifier = modifier
使用以下示例数据:

id    user_id    ticket_md_id
1     1          1
2     2          1
3     3          1
4     1          2
5     2          2
id    first_name    last_name    won
1     Rob           Stark        False
2     Stan          Clark        False
3     Tom           Dark         False
id    raffle_type    description    modifier
1     type_1         blah blah      21
2     type_2         blah blah      5
A
用户
表:

class RaffleModel(db.Model):
    __tablename__ = 'raffles'

    id = db.Column(db.Integer, primary_key=True)

    # relationship to users
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    user = db.relationship("UserModel", backref="raffles")

    # relationship to ticket_md
    ticket_md_id = db.Column(db.Integer, db.ForeignKey('ticket_mds.id'))
    ticket_md = db.relationship("TicketMetaDataModel", backref="raffles")

    def __init__(self, user, ticket_md):
        self.user = user
        self.ticket_md = ticket_md
class UserModel(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(25))
    last_name = db.Column(db.String(25))
    won = db.Column(db.Boolean, default=False, nullable=False)

    # has backref via user.raffles

    def __init__(self, first_name, last_name, won):
        self.first_name = first_name
        self.last_name = last_name
        self.won = won
class TicketMetaDataModel(db.Model):
    __tablename__ = 'ticket_mds'

    id = db.Column(db.Integer, primary_key=True)
    raffle_type = db.Column(db.String(20))
    description = db.Column(db.String(200))
    modifier = db.Column(db.Integer)

    # has backref via ticket_md.raffles

    def __init__(self, raffle_type, description, modifier):
        self.raffle_type = raffle_type
        self.description = description
        self.modifier = modifier
使用以下示例数据:

id    user_id    ticket_md_id
1     1          1
2     2          1
3     3          1
4     1          2
5     2          2
id    first_name    last_name    won
1     Rob           Stark        False
2     Stan          Clark        False
3     Tom           Dark         False
id    raffle_type    description    modifier
1     type_1         blah blah      21
2     type_2         blah blah      5
最后是一个
ticket\u mds
表:

class RaffleModel(db.Model):
    __tablename__ = 'raffles'

    id = db.Column(db.Integer, primary_key=True)

    # relationship to users
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    user = db.relationship("UserModel", backref="raffles")

    # relationship to ticket_md
    ticket_md_id = db.Column(db.Integer, db.ForeignKey('ticket_mds.id'))
    ticket_md = db.relationship("TicketMetaDataModel", backref="raffles")

    def __init__(self, user, ticket_md):
        self.user = user
        self.ticket_md = ticket_md
class UserModel(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(25))
    last_name = db.Column(db.String(25))
    won = db.Column(db.Boolean, default=False, nullable=False)

    # has backref via user.raffles

    def __init__(self, first_name, last_name, won):
        self.first_name = first_name
        self.last_name = last_name
        self.won = won
class TicketMetaDataModel(db.Model):
    __tablename__ = 'ticket_mds'

    id = db.Column(db.Integer, primary_key=True)
    raffle_type = db.Column(db.String(20))
    description = db.Column(db.String(200))
    modifier = db.Column(db.Integer)

    # has backref via ticket_md.raffles

    def __init__(self, raffle_type, description, modifier):
        self.raffle_type = raffle_type
        self.description = description
        self.modifier = modifier
使用以下示例数据:

id    user_id    ticket_md_id
1     1          1
2     2          1
3     3          1
4     1          2
5     2          2
id    first_name    last_name    won
1     Rob           Stark        False
2     Stan          Clark        False
3     Tom           Dark         False
id    raffle_type    description    modifier
1     type_1         blah blah      21
2     type_2         blah blah      5
我在这里的问题在于,我似乎无法找到一个查询来获取用户从莱佛士表中分组的票点总和(基于
TicketMetaDataModel.modifier
属性),以以下格式返回结果:

总分

e、 g:

我尝试了以下方法(但没有进一步尝试):


如果我没弄错你的问题。您正试图根据通过联接获得的值进行分组

from sqlalchemy import func
query = db.session.query(UserModel.first_name, UserModel.last_name, func.sum(TicketMetaDataModel.modifier))
query = query.join(RaffleModel,RaffleModel.user_id==UserModel.id).join(RaffleModel.ticket_md_id==TicketMetaDataModel.id)
.group_by(UserModel.first_name, UserModel.last_name)

它应该会给你所需的结果

它让我很感兴趣,我做了一个独立的例子

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, ForeignKey, String, Boolean
from sqlalchemy.orm import relationship, sessionmaker

from pprint import pformat as pf

Base = declarative_base()

class ReprMixin(object):

    """A mixin to implement a generic __repr__ method"""

    def as_dict(self):
        """return instance as a dictionary"""
        return {c.name: getattr(self, c.name) for c in self.__table__.columns}

    def __repr__(self):
        return '<%s(%s)>' % (self.__class__.__name__, ', '.join([f'{c.name} = {getattr(self, c.name)}' for c in self.__table__.columns]))

class RaffleModel(ReprMixin, Base):
    __tablename__ = 'raffles'

    id = Column(Integer, primary_key=True)

    # relationship to users
    user_id = Column(Integer, ForeignKey('users.id'))
    user = relationship("UserModel", backref="raffles")

    # relationship to ticket_md
    ticket_md_id = Column(Integer, ForeignKey('ticket_mds.id'))
    ticket_md = relationship("TicketMetaDataModel", backref="raffles")

    def __init__(self, user, ticket_md):
        self.user = user    
        self.ticket_md = ticket_md

    @classmethod
    def insert_defaults(cls, session):
        for user_id, ticket_id in zip([1,2,3,1,2],[1,1,1,2,2]):
            user = session.query(UserModel).filter_by(id=user_id).scalar()
            ticket = session.query(TicketMetaDataModel).filter_by(id=ticket_id).scalar()
            session.add(cls(user, ticket))
        session.commit()


class UserModel(ReprMixin, Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    first_name = Column(String(25))
    last_name = Column(String(25))
    won = Column(Boolean, default=False, nullable=False)

    # has backref via user.raffles

    def __init__(self, first_name, last_name, won):
        self.first_name = first_name
        self.last_name = last_name
        self.won = won

    @classmethod
    def insert_defaults(cls, session):
        for first_name, last_name, won in zip("Rob Stan Tom".split(),"Stark Clark Dark".split(), [False]*3):
            session.add(cls(first_name, last_name, won))
        session.commit()


class TicketMetaDataModel(ReprMixin, Base):
    __tablename__ = 'ticket_mds'

    id = Column(Integer, primary_key=True)
    raffle_type = Column(String(20))
    description = Column(String(200))
    modifier = Column(Integer)

    # has backref via ticket_md.raffles

    def __init__(self, raffle_type, description, modifier):
        self.raffle_type = raffle_type
        self.description = description
        self.modifier = modifier

    @classmethod
    def insert_defaults(cls, session):
        for raffle_type, description, modifier in zip("type1 type2".split(), "desc1 desc2".split(), [21,5]):
            session.add(cls(raffle_type, description, modifier))
        session.commit()

if __name__ == '__main__':


    from pprint import pprint as pp
    engine = create_engine('sqlite://')
    Session = sessionmaker()

    sess = Session(bind=engine)

    Base.metadata.create_all(bind=engine)

    TicketMetaDataModel.insert_defaults(sess)
    UserModel.insert_defaults(sess)
    RaffleModel.insert_defaults(sess)


    print('************************')
    pp(sess.query(UserModel).all())
    print('************************')
    pp(sess.query(RaffleModel).all())
    print('************************')
    pp(sess.query(TicketMetaDataModel).all())


    from sqlalchemy import func
    query = sess.query(UserModel.first_name, UserModel.last_name, func.sum(TicketMetaDataModel.modifier))

    query2 = query.join(RaffleModel.user)\
                .join(RaffleModel.ticket_md)\
                .group_by(UserModel.first_name, UserModel.last_name)

    print('************************')
    print(query)
    print(query.all())
    print('************************')
    print(query2.all())
    print(query2)

    Base.metadata.drop_all(engine)
来自sqlalchemy.ext.declarative import declarative\u base
从sqlalchemy导入创建引擎
从sqlalchemy导入列,整数,外键,字符串,布尔值
从sqlalchemy.orm导入关系,sessionmaker
从pprint导入pformat作为pf
Base=声明性_Base()
类ReprMixin(对象):
“”“用于实现泛型_urepr__u;方法的mixin”“”
定义为(自身):
“”“将实例作为字典返回”“”
返回{c.name:getattr(self,c.name),用于self中的c。_table__.columns}
定义报告(自我):
返回“%”(self.\uuuuuu class.\uuuuuu name.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
类别抽彩模型(ReprMixin,基本):
__tablename_uuu=‘莱佛士’
id=列(整数,主键=True)
#与用户的关系
user\u id=列(整数,ForeignKey('users.id'))
用户=关系(“用户模型”,backref=“莱佛士”)
#与票证的关系
ticket\u md\u id=列(整数,ForeignKey('ticket\u mds.id'))
票证=关系(“票证元数据模型”,backref=“莱佛士”)
定义初始化(自我、用户、票证管理):
self.user=用户
self.ticket\u md=ticket\u md
@类方法
def insert_默认值(cls,会话):
对于用户id,zip中的票证id([1,2,3,1,2],[1,1,1,2,2]):
user=session.query(UserModel).filter\u by(id=user\u id).scalar()
ticket=session.query(TicketMetaDataModel).filter\u by(id=ticket\u id).scalar()
会话添加(cls(用户、票据))
session.commit()
类UserModel(ReprMixin,Base):
__tablename_uu='users'
id=列(整数,主键=True)
first_name=列(字符串(25))
姓氏=列(字符串(25))
WIN=列(布尔值,默认值=False,可空值=False)
#已通过user.raffles获得backref
def_uuuinit_uuu(self,first_name,last_name,won):
self.first\u name=first\u name
self.last\u name=last\u name
self.won=won
@类方法
def insert_默认值(cls,会话):
名字、姓氏以zip赢得(“Rob Stan Tom.split(),“Stark Clark Dark.split(),[False]*3”):
会话添加(cls(名字、姓氏、韩元))
session.commit()
类TicketMetaDataModel(ReprMixin,Base):
__tablename_uuu='ticket_mds'
id=列(整数,主键=True)
抽奖类型=列(字符串(20))
description=列(字符串(200))
修饰符=列(整数)
#已通过莱佛士车票返回
定义初始值(自我、抽奖类型、描述、修饰符):
self.raffle\u type=抽奖类型
self.description=描述
self.modifier=修饰符
@类方法
def insert_默认值(cls,会话):
对于抽奖类型、说明、zip中的修饰符(“type1 type2.split(),“desc1 desc2.split(),[21,5]):
会话添加(cls(抽奖类型、说明、修改器))
session.commit()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
从pprint导入pprint作为pp
engine=create_engine('sqlite://'))
Session=sessionmaker()
sess=会话(绑定=引擎)
Base.metadata.create_all(bind=engine)
TicketMetaDataModel.insert_默认值(sess)
UserModel.insert_默认值(sess)
RaffleModel.insert_默认值(sess)
打印(“****************************”)
pp(sess.query(UserModel.all())
打印(“****************************”)
pp(sess.query(RaffleModel.all())
打印(“****************************”)
pp(sess.query(TicketMetaDataModel.all())
从sqlalchemy导入函数
query=sess.query(UserModel.first\u name、UserModel.last\u name、func.sum(TicketMetaDataModel.modifier))
query2=query.join(RaffleModel.user)\
.join(莱佛士模式门票)\
.group_by(UserModel.first_name,UserModel.last_name)
打印(“****************************”)
打印(查询)
打印(query.all())
打印(“****************************”)
打印(query2.all())
打印(查询2)
Base.metadata.drop_all(引擎)
运行它会返回

************************
[<UserModel(id = 1, first_name = Rob, last_name = Stark, won = False)>,
 <UserModel(id = 2, first_name = Stan, last_name = Clark, won = False)>,
 <UserModel(id = 3, first_name = Tom, last_name = Dark, won = False)>]
************************
[<RaffleModel(id = 1, user_id = 1, ticket_md_id = 1)>,
 <RaffleModel(id = 2, user_id = 2, ticket_md_id = 1)>,
 <RaffleModel(id = 3, user_id = 3, ticket_md_id = 1)>,
 <RaffleModel(id = 4, user_id = 1, ticket_md_id = 2)>,
 <RaffleModel(id = 5, user_id = 2, ticket_md_id = 2)>]
************************
[<TicketMetaDataModel(id = 1, raffle_type = type1, description = desc1, modifier = 21)>,
 <TicketMetaDataModel(id = 2, raffle_type = type2, description = desc2, modifier = 5)>]
************************
SELECT users.first_name AS users_first_name, users.last_name AS users_last_name, sum(ticket_mds.modifier) AS sum_1 
FROM users, ticket_mds
[('Tom', 'Dark', 78)]
************************
[('Rob', 'Stark', 26), ('Stan', 'Clark', 26), ('Tom', 'Dark', 21)]
SELECT users.first_name AS users_first_name, users.last_name AS users_last_name, sum(ticket_mds.modifier) AS sum_1 
FROM raffles JOIN users ON users.id = raffles.user_id JOIN ticket_mds ON ticket_mds.id = raffles.ticket_md_id GROUP BY users.first_name, users.last_name
************************
[,
,
]
************************
[,
,
,
,
]
************************
[,
]
************************
选择users.first\u name作为users\u first\u name,users.last\u name作为users\u last\u name,sum(ticket\u mds.modifier)作为sum\u 1
来自用户、票证和mds
[('Tom','Dark',78)]
************************
[('Rob','Stark',26),('Stan','Clark',26),('Tom','Dark',21)]
选择users.first\u name作为users\u first\u name,users.last\u name作为users\u last\u name,sum(ticket\u mds.modifier)作为sum\u 1
来自莱佛士加入用户组。id=莱佛士。用户\U id加入票证上的票证\U mds。id=莱佛士。票证\U md\U id用户组。名字,用户。姓氏
如果
RaffleModel
是一个男人的关联表,那么你的模型将受益匪浅