如何在SQLAlchemy中的GROUP BY之后对算术表达式进行ORDER BY?

时间:2016-01-10 11:25:25

标签: python sql flask sqlalchemy flask-sqlalchemy

我的表:

tb{
caller:string
callee:string
success:boolean
time: datetime
}

这个表是一个调用状态表,每次函数调用另一个函数后,调用者都会存储自己的名字,它调用的函数,调用状态(成功或失败)以及我数据库中的调用时间。

现在我想用SQL或Flask-SQLAlchemy获得如下结果:

result(caller,callee, success_count, total_count, success_ratio)

我想得到每个元组(来电者,被调用者)分组的success_count,total_count和success_ratio的统计数据,并按success_ratio排序。

如何使用SQL语句或Flask-SQLAlchemy执行此操作?

1 个答案:

答案 0 :(得分:0)

让我们考虑以下示例callstate表。

+-----------+---------------+----------+---------------------+
| 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 |
+-----------+---------------+----------+---------------------+

用于获取统计信息的简单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

SQLAlchemy中的类似查询。例如,这是纯SQLAlchemy,但在Flask-SQLAlchemy的情况下,查询部分应该非常相似。

#!/usr/bin/env python

from sqlalchemy import *
from sqlalchemy.orm import sessionmaker

engine = create_engine('mysql+mysqldb://johndoe@localhost:3306/so_callstate')
connection = engine.connect()
Session = sessionmaker(bind=engine)
session = Session()

cs = Table('callstate', MetaData(),
    Column('caller', String()),
    Column('callee', String()),
    Column('success', Boolean())
)

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'))

for row in result:
    print(row)

基于上述示例的示例输出。

('Bar::baz', 'Lorem::ipsum', Decimal('4'), 5L, Decimal('0.8000'))
('Foo::bar', 'Lorem::ipsum', Decimal('3'), 4L, Decimal('0.7500'))
('Bar::baz', 'Qux::foo', Decimal('1'), 3L, Decimal('0.3333'))
('Foo::bar', 'Qux::foo', Decimal('0'), 2L, Decimal('0.0000'))
('Bar::baz', 'Dolor::sit', Decimal('0'), 2L, Decimal('0.0000'))
('Foo::bar', 'Dolor::sit', Decimal('0'), 1L, Decimal('0.0000'))