flask_sqlalchemy和SQL遇到的一个查询

最近需要统计系统调用之间的成功率,使用的ORM是sqlalchemy,我的数据库表如下所示:

+-----------+---------------+----------+---------------------+
| caller    | callee        | success  | time                |
+-----------+---------------+----------+---------------------+
| Bar::baz  | Dolor::sit    | 0        | 2016-01-07 00:00:00 |
| Bar::baz  | Dolor::sit    | 0        | 2016-01-05 00:00:00 |
| Bar::baz  | Lorem::ipsum  | 0        | 2016-01-01 00:00:00 |
| Bar::baz  | Lorem::ipsum  | 1        | 2016-01-04 00:00:00 |
| Bar::baz  | Lorem::ipsum  | 1        | 2016-01-09 00:00:00 |
| Bar::baz  | Lorem::ipsum  | 1        | 2016-01-08 00:00:00 |
| Bar::baz  | Lorem::ipsum  | 1        | 2016-01-04 00:00:00 |
| Bar::baz  | Qux::foo      | 0        | 2016-01-05 00:00:00 |
| Bar::baz  | Qux::foo      | 0        | 2016-01-01 00:00:00 |
| Bar::baz  | Qux::foo      | 1        | 2016-01-05 00:00:00 |
| Foo::bar  | Dolor::sit    | 0        | 2016-01-06 00:00:00 |
| Foo::bar  | Lorem::ipsum  | 0        | 2016-01-08 00:00:00 |
| Foo::bar  | Lorem::ipsum  | 1        | 2016-01-03 00:00:00 |
| Foo::bar  | Lorem::ipsum  | 1        | 2016-01-05 00:00:00 |
| Foo::bar  | Lorem::ipsum  | 1        | 2016-01-07 00:00:00 |
| Foo::bar  | Qux::foo      | 0        | 2016-01-07 00:00:00 |
| Foo::bar  | Qux::foo      | 0        | 2016-01-04 00:00:00 |
+-----------+---------------+----------+---------------------+
我需要统计每一对调用的总次数,成功次数,成功率,并且按照成功率进行排序,返回的期望数据应该是:

result(callercallee, success_count, total_count, success_ratio)

我一时没有想到比较好的办法,在stackoverflow上面问了之后有大神给出详细的答案

result = session.query(
    cs.c.caller,
    cs.c.callee,
    func.sum(cast(cs.c.success, Integer).label('success_count'),
    func.count().label('total_count'),
    (func.sum(cast(cs.c.success, Integer)) / func.count()).label('success_ratio')
).group_by(cs.c.caller, cs.c.callee).order_by(desc('success_ratio'))
还有对应的sql语句

SELECT caller,
       callee,
       sum(success) AS 'success_count',
       count(*) AS 'total_count',
       sum(success) / count(*) AS 'success_ratio'
FROM callstate
GROUP BY caller, callee
ORDER BY success_ratio DESC
让我解了燃眉之急

我用的python flask-sqlalchemy

下面是我的表结构

class State(db.Model):
    __tablename__ = 'states'
    _id = db.Column(db.Integer, primary_key=True)
    caller = db.Column(db.String(64), nullable=False)
    caller_fn = db.Column(db.String(64), nullable=False)
    callee = db.Column(db.String(64), nullable=False)
    callee_fn = db.Column(db.String(64), nullable=False)
    success = db.Column(db.Boolean, nullable=False)
    time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    msg = db.Column(db.String(256))


然后我的查询使用到三个label解决了这个问题

all_count = label('all_count', func.count(State._id))
success_count = label('success_count', func.sum(case(
        [(State.success, 1)], else_=0)))
success_ratio = label('success_ratio', success_count / all_count)
这三个label在几乎任何条件的查询中,只要是需要得到调用成功数,成功率,调用总数,就可以服用,与查询条件无关

比如这样的

query = db.session.query(State.caller, State.callee,
                         all_count, success_count, success_ratio)
这样的

query = db.session.query(State.caller_fn, all_count,
                         success_count, success_ratio).group_by(State.caller_fn). \
    filter_by(caller=caller)
还有这样的

query = db.session.query(State.callee, State.callee_fn, all_count, success_count,
                         success_ratio).group_by(State.callee, State.callee_fn). \
    filter_by(caller=caller, caller_fn=caller_fn)

等等


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章