【SQLAlchemy】04-SQLAlchemy高级查询

好风凭借力,送我上青云。

1. 排序

1.1 order_by

  • 正序
session.query(Article).order_by("-create_time").all()
  • 逆序:个人测试无法直接使用-create_time方式,需要导入text
from sqlalchemy import text
session.query(Article).order_by(text("-create_time")).all()

1.2 __mapper_args__

class Article(Base):
	......
        __mapper_args__ = {
            "order_by": create_time,
            # 倒叙方式一
            "order_by": create_time.desc()
            # 倒叙方式二
            "order_by": text("-create_time")
        }

2. 限制查询

2.1 limit

可以限制每次查询的时候只查询几条数据。例如:查询前10条

session.query(Article).limit(10).all()

2.2 offset

可以限制查找数据的时候过偏移条。例如:从第10条开始取10条

session.query(Article).offset(10).limit(10).all()

2.3 slice

可以对Query对象使用切片操作,来获取想要的数据。例如:获取时间排序的后10条

session.query(Article).order_by(Article.create_time.desc()).slice(0,10).all()

# 列表切片的方式获取,后缀不需要加all()
session.query(Article).order_by(Article.create_time.desc())[0:10]

3. 懒加载

当我们通过外键查询的时候不是直接获取相对应的数据,而是返回一个类似于Query的对象,这样我们就可以继续进行相应的条件过滤。

那么这时候就可以考虑使lazy='dynamic',其返回的是AppenderQuery对象了,这个对象继承Query因此拥有Query所有的过滤方法

lazy可用的选项:

  1. select:这个是默认选项。还是拿user.articles的例子来讲。如果你没有访问user.articles这个属性,那么sqlalchemy就不会从数据库中查找文章。一旦你访问了这个属性,那么sqlalchemy就会立马从数据库中查找所有的文章,并把查找出来的数据组装成一个列表返回。这也是懒加载。
  2. dynamic:在访问user.articles的时候返回回来的不是一个列表,而是AppenderQuery对象。
class Article(Base):
    ......

    # 一般懒加载用于一查多,因此定义在反向查询中
    author = relationship("User",backref=backref("articles",lazy="dynamic"))

4. 分组查询、过滤、连接和子查询

4.1 group_by

根据某个字段进行分组。比如想要根据性别进行分组,来统计每个分组分别有多少人。

session.query(User.gender,func.count(User.id)).group_by(User.gender).all()

>>>[('male',2),('female',1)]

4.2 having

having是对查找结果进一步过滤。比如只想要看未成年人的数量,那么可以首先对年龄进行分组统计人数,然后再对分组进行having过滤。

session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age >= 18).all()

4.3 join

join分为left join(左外连接)和right join(右外连接)以及内连接(等值连接)

比如现在要实现一个功能,要查找所有用户,按照发表文章的数量来进行排序。

session.query(User,func.count(Article.id)).join(Article).group_by(User.id).order_by(func.count(Article.id).desc()).all()

4.4 subquery

子查询可以让多个查询变成一个查询,只要查找一次数据库,性能相对来讲更加高效一点

那么在sqlalchemy中,要实现一个子查询,应该使用以下几个步骤:

  1. 将子查询按照传统的方式写好查询代码,然后在query对象后面执行subquery方法,将这个查询变成一个子查询。
  2. 在子查询中,将以后需要用到的字段通过label方法,取个别名。
  3. 在父查询中,如果想要使用子查询的字段,那么可以通过子查询的返回值上的c属性拿到。
sq = session.query(User.city.label("city"),User.age.label("age")).filter(User.username=='xxx').subquery()

session.query(User).filter(User.city==sq.c.city,User.age==sq.c.age).all()
原文地址:https://www.cnblogs.com/ydongy/p/13158051.html