在Flask-SqlAlchemy

时间:2015-10-31 12:18:47

标签: python flask sqlalchemy flask-sqlalchemy

我有三张桌子。一个用groupid列定义组,另外两个定义用户和事件,每个用户和事件都属于一个组。

class InterestGroup(db.Model):
        __tablename__ = "interest_groups"
        groupid = db.Column(db.Integer, primary_key=True)
        groupcode = db.Column(db.String(10))
        groupname = db.Column(db.String(200), unique=True)

class InterestGroupEvent(db.Model):
        __tablename__ = "interest_group_events"
        eventid = db.Column(db.Integer, db.ForeignKey("social_events.eventid"), primary_key=True)
        groupid = db.Column(db.Integer, db.ForeignKey("interest_groups.groupid"), primary_key=True)

class InterestGroupUser(db.Model):
        __tablename__ = "interest_group_users"
        userid = db.Column(db.Integer, db.ForeignKey("users.userid"), primary_key=True)
        groupid = db.Column(db.Integer, db.ForeignKey("interest_groups.groupid"), primary_key=True)

我想列出所有群组,包括每个群组的用户数量和事件数量,即使没有任何用户也是如此。

我可以获得我需要的所有数据,如下所示:

    IGs = InterestGroup.query.all()
    IGEs = (
            db.session.query(
                    InterestGroupEvent.groupid,
                    func.count(InterestGroupEvent.groupid)
                    )
            .group_by(InterestGroupEvent.groupid)
            .all()
            )
    IGUs = (
            db.session.query(
                    InterestGroupUser.groupid,
                    func.count(InterestGroupUser.groupid)
                    )
            .group_by(InterestGroupUser.groupid)
            .all()
            )
    return json.dumps({
            "groups": [{"groupid": IG.groupid} for IG in IGs],
            "events": [{"groupid": IGE.groupid, "count": IGE[1]} for IGE in IGEs],
            "users": [{"groupid": IGU.groupid, "count": IGU[1]} for IGU in IGUs]
            })

返回以下内容:

{
    "events": [
        {
            "count": 2,
            "groupid": 1
        },
        {
            "count": 1,
            "groupid": 2
        }
    ],
    "groups": [
        {
            "groupid": 1
        },
        {
            "groupid": 2
        },
        {
            "groupid": 3
        }
    ],
    "users": [
        {
            "count": 2,
            "groupid": 1
        },
        {
            "count": 1,
            "groupid": 3
        }
    ]
}

但我想要的是以下内容:

[
    {
        "groupid": 1,
        "eventcount": 2,
        "usercount": 2
    },
    {
        "groupid": 2,
        "eventcount": 1,
        "usercount": 0
    },
    {
        "groupid": 3,
        "eventcount": 0,
        "usercount": 1
    }
]

显然我可以手动合并它,但我确信有一种方法可以在单个查询中直接从数据库中获取它。我尝试过以下方法:

    IGs = (
            db.session.query(InterestGroup.groupid,
                             func.count(InterestGroupEvent.groupid),
                             func.count(InterestGroupUser.groupid)
                             )
            .group_by(InterestGroup.groupid)
            .all()
    )
    return json.dumps([{"groupid": IG[0], "eventcount": IG[1], "usercount": IG[2]} for IG in IGs])

但是这会返回:

[
    {
        "usercount": 9,
        "groupid": 1,
        "eventcount": 9
    },
    {
        "usercount": 9,
        "groupid": 2,
        "eventcount": 9
    },
    {
        "usercount": 9,
        "groupid": 3,
        "eventcount": 9
    }
]
嗯,这很接近:

    IGs = (
            db.session.query(InterestGroup.groupid,
                             func.count(InterestGroupEvent.groupid),
                             func.count(InterestGroupUser.groupid)
                             )
            .outerjoin(InterestGroupEvent)
            .outerjoin(InterestGroupUser)
            .group_by(InterestGroup.groupid)
            .all()
    )
    return json.dumps([
            {"groupid": IG[0], "eventcount": IG[1], "usercount": IG[2]} for IG in IGs
            ])

它返回:

[
    {
        "usercount": 4,
        "groupid": 1,
        "eventcount": 4
    },
    {
        "usercount": 0,
        "groupid": 2,
        "eventcount": 1
    },
    {
        "usercount": 1,
        "groupid": 3,
        "eventcount": 0
    }
]

但是第1组的计数是错误的。我该怎么办呢?

修改

在没有更好的解决方案的情况下,这似乎有效并且现在可以做到:

    IGEs = (
            InterestGroup.query
            .outerjoin(InterestGroupEvent)
            .add_columns(func.count(InterestGroupEvent.groupid))
            .group_by(InterestGroup.groupid)
            .order_by(InterestGroup.groupid)
            .all()
    )
    IGUs = (
            InterestGroup.query
            .outerjoin(InterestGroupUser)
            .add_columns(func.count(InterestGroupUser.groupid))
            .group_by(InterestGroup.groupid)
            .order_by(InterestGroup.groupid)
            .all()
    )
    results = []
    for i in range(len(IGEs)):
            results.append({"groupid": IGEs[i][0].groupid, "eventcount": IGEs[i][1], "usercount": IGUs[i][1]})
    return json.dumps(results)

但我仍然想知道如何通过一个查询来完成它。

0 个答案:

没有答案
相关问题