Flask ORM 学习笔记Part09:数据查询(中)
  qdp7fV9qUjiK 2023年12月12日 13 0

聚合操作

聚合操作是指对一组值进行汇总、计算或统计的操作。这些操作通常应用于数据库中的列(字段),并用于生成单个标量值(例如平均值AVG、总和SUM、最大值MAX、最小值MIN、计数COUNT等)。

示例代码

from app import app
from model import *
from pprint import pprint
from sqlalchemy import func

with app.app_context():

    # 查询最大值
    pprint("查询最大值")
    pprint("db.session.query(func.max(Profile.age)).scalar()")
    max_age = db.session.query(func.max(Profile.age)).scalar()
    pprint(max_age)

    pprint("Profile.query.with_entities(func.max(Profile.age)).scalar()")
    max_age = Profile.query.with_entities(func.max(Profile.age)).scalar()
    pprint(max_age)

    # 查询平均值
    pprint("查询平均值")
    pprint("db.session.query(func.avg(Profile.age)).scalar()")
    avg_age = db.session.query(func.avg(Profile.age)).scalar()
    pprint(avg_age)

    pprint("Profile.query.with_entities(func.avg(Profile.age)).scalar()")
    avg_age = Profile.query.with_entities(func.avg(Profile.age)).scalar()
    pprint(avg_age)

    # 查询总和
    pprint("查询总和")
    pprint("db.session.query(func.sum(Profile.age)).scalar()")
    sum_age = db.session.query(func.sum(Profile.age)).scalar()
    pprint(sum_age)

    pprint("Profile.query.with_entities(func.sum(Profile.age)).scalar()")
    sum_age = Profile.query.with_entities(func.sum(Profile.age)).scalar()
    pprint(sum_age)

    # 查询最小值
    pprint("查询最小值")
    pprint("db.session.query(func.min(Profile.age)).scalar()")
    min_age = db.session.query(func.min(Profile.age)).scalar()
    pprint(min_age)

    pprint("Profile.query.with_entities(func.min(Profile.age)).scalar()")
    min_age = Profile.query.with_entities(func.min(Profile.age)).scalar()
    pprint(min_age)

    # 查询总和
    pprint("查询总和")
    pprint("db.session.query(func.count(Profile.age)).scalar()")
    total_age = db.session.query(func.sum(Profile.age)).scalar()
    pprint(total_age)

    pprint("Profile.query.with_entities(func.sum(Profile.age)).scalar()")
    total_age = Profile.query.with_entities(func.sum(Profile.age)).scalar()
    pprint(total_age)

    # 查询最大值
    pprint("查询最大值")
    pprint("db.session.query(func.max(Profile.age)).scalar()")
    max_age = db.session.query(func.max(Profile.age)).scalar()
    pprint(max_age)


    # 查询记录数
    pprint("查询记录数")
    pprint("db.session.query(db.func.count(Profile.age)).scalar()")
    profile_count = db.session.query(db.func.count(Profile.age)).scalar()
    pprint(profile_count)

    pprint("Profile.query.with_entities(db.func.count(Profile.age)).scalar()")
    profile_count = Profile.query.with_entities(db.func.count(Profile.age)).scalar()
    pprint(profile_count)

返回结果

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy

代码说明

在这个示例中,我用了 func.max、func.avg、func.min、func.sum、func.count 等函数来执行聚合操作。这些函数可以应用到模型类的属性上,以完成相应的数据库查询操作。

请注意,这些查询返回的是标量值,可直接在模型类上进行调用,而无需额外的 db.session.query。这样的查询语法相对更简洁一些。

with_entities 是 SQLAlchemy 中的方法,用于指定查询返回的字段或表达式。在 Flask-SQLAlchemy 中,这个方法可以用于查询时选择特定的字段或执行聚合操作。这样更贴近模型类的语法风格,使代码更加清晰。


执行方法\终端方法

在SQLAlchemy中有一列方法用于触发实际的 SQL 查询并返回结果,这些方法通常有统一的名字——“执行方法”或“终端方法”。

all()

执行查询并返回所有结果,以列表的形式返回。

from app import app
from model import *
from pprint import pprint

with app.app_context():
    r = Profile.query.all()
    pprint(r)

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_02

first()

执行查询并返回结果中的第一条记录,如果没有结果则返回 None。

from app import app
from model import *
from pprint import pprint

with app.app_context():
    r = Profile.query.filter(Profile.gender == 'M').first()
    pprint(r

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_03

one()

执行查询并返回结果中的唯一记录,如果结果不唯一或者没有结果,则引发 sqlalchemy.orm.exc.NoResultFound 或 sqlalchemy.orm.exc.MultipleResultsFound 异常。

from app import app
from model import *
from pprint import pprint

with app.app_context():
    try:
        r = Profile.query.filter(Profile.gender == 'M').one()
        pprint(r)
    except Exception as e:  # gender为M的记录不止一个,导致异常
        pprint(str(e))

    r = Profile.query.filter(Profile.gender == 'F').one()
    pprint(r)

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_04

scalar()

执行查询并返回结果的第一列的第一个元素,通常用于获取聚合操作的标量值。

scalar()用法已经在上文所体现,不再赘述。

count()

执行查询并返回结果的数量。

同样的,有关于count()的代码在上文中已有所体现。

update(values, synchronize_session='evaluate'):

用于执行更新操作,更新满足条件的记录。

from app import app
from model import *
from pprint import pprint

with app.app_context():
    r = Profile.query.filter(Profile.id == 1).one()
    pprint('更新前数据')
    pprint(r)
    
    Profile.query.filter(Profile.id == 1).update({"fullname": "李四"})
    
    r = Profile.query.filter(Profile.id == 1).one()
    pprint('更新后数据')
    pprint(r)

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_05

delete(synchronize_session='evaluate')

用于执行删除操作,删除满足条件的记录。

MyModel.query.filter_by(id=1).delete()
db.session.commit()

注意 关于synchronize_session='evaluate'

synchronize_session 参数在 SQLAlchemy 的 update 和 delete 操作中用于指定在执行更新或删除后如何同步会话(session)中的状态。该参数有三个可能的值:

'evaluate':

这是默认值。在执行更新或删除操作后,会话会尝试智能地评估哪些对象的状态应该被同步,从而减少需要刷新对象状态的次数。这样可以提高性能。

'fetch':

在执行更新或删除后,会话会强制从数据库中获取所有相关的对象以确保它们的状态是最新的。这会导致更多的数据库查询,但确保了对象状态的准确性。

'unsynchronize':

在执行更新或删除后,不会自动同步会话中的对象状态。这意味着你需要手动调用 session.expire_all() 或 session.expire(object) 来刷新对象状态。

在 update 和 delete 操作中,默认值 'evaluate' 通常是合适的,因为它会尽力减少不必要的数据库查询,同时仍然保持对象状态的一致性。然而,具体的选择取决于你的应用程序的需求和性能考虑。


join()

用于执行关联查询,将两个表连接起来,并返回结果。

from app import app
from model import *
from pprint import pprint

with app.app_context():
    r = Profile.query.filter(Profile.id == 1).join(Account, Account.id == Profile.account_id).add_entity(Account).all()
    pprint(r)

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_06

在 SQLAlchemy 中,add_entity 并不是直接用于执行查询的方法,而是用于构建复杂查询时,将其他实体(Entity)添加到查询中的一种方法。它通常用于联合查询(Join)或者复杂查询场景。

在这个join示例中,就是通过add_entity返回两个实例

distinct()

用于执行去重操作,返回查询结果中的唯一记录。

from app import app
from model import *
from pprint import pprint

with app.app_context():
    r = Profile.query.with_entities(Profile.gender).distinct().all()
    pprint(r)

    r = Profile.query.with_entities(Profile.gender, Profile.fullname).distinct().all()
    pprint(r)

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_07

group_by(*args)

用于执行分组操作,将结果按照指定的列进行分组。

from app import app
from model import *
from pprint import pprint
from sqlalchemy import func

with app.app_context():
    r = db.session.query(Profile.gender, func.count().label('count')).group_by(Profile.gender).all()
    pprint(r)

    r = Profile.query.with_entities(Profile.gender, func.count().label('count')).group_by(Profile.gender).all()
    pprint(r)

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_08

having(criterion)

用于在分组后的结果上执行条件筛选。

from app import app
from model import *
from pprint import pprint
from sqlalchemy import func

with app.app_context():
    r = db.session.query(Profile.gender, func.count().label('count')).group_by(Profile.gender)\
        .having(func.count() > 1).all()
    pprint(r)

    r = Profile.query.with_entities(Profile.gender, func.count().label('count')).group_by(Profile.gender)\
        .having(func.count() > 1).all()
    pprint(r)

Flask ORM 学习笔记Part09:数据查询(中)_sqlalchemy_09

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月12日 0

暂无评论

qdp7fV9qUjiK