1、排序

  • 排序概述:

    1. order_by:可以指定根据这个表中的某个字段进行排序,如果在前面加了一个-,代表的是降序排序。

    2. 在模型定义的时候指定默认排序:有些时候,不想每次在查询的时候都指定排序的方式,可以在定义模型的时候就指定排序的方式。有以下两种方式:

      • relationship的order_by参数:在指定relationship的时候,传递order_by参数来指定排序的字段。

      • 在模型定义中,添加以下代码,即可让文章使用标题来进行排序。

         __mapper_args__ = {
        "order_by": title
        }
    3. 正序排序与倒序排序:默认是使用正序排序。如果需要使用倒序排序,那么可以使用这个字段的desc()方法,或者是在排序的时候使用这个字段的字符串名字,然后在前面加一个负号。

  • 代码示例:

2、limit、offset和切片操作

  • limit、offset和切片操作概述:

    1. limit:可以限制每次查询的时候只查询几条数据。
    2. offset:可以限制查找数据的时候过滤掉前面多少条。
    3. 切片:可以对Query对象使用切片操作,来获取想要的数据。可以使用slice(start,stop)方法来做切片操作。也可以使用[start:stop]的方式来进行切片操作。一般在实际开发中,中括号的形式是用得比较多的。希望大家一定要掌握。示例代码如下:
    articles = session.query(Article).order_by(Article.id.desc())[0:10]
  • 代码示例:

    class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    create_time = Column(DateTime,nullable=False,default=datetime.now)
    uid = Column(Integer,ForeignKey("user.id")) author = relationship("User",backref=backref("articles")) __mapper_args__ = {
    "order_by": create_time.desc()
    } def __repr__(self):
    return "<Article(title:%s,create_time:%s)>" % (self.title,self.create_time) # 倒序排序
    articles = session.query(Article).all()
    print(articles)

3、懒加载

  • 懒加载概述:

    1、在一对多,或者多对多的时候,如果想要获取多的这一部分的数据的时候,往往能通过一个属性就可以全部获取了。比如有一个作者,想要或者这个作者的所有文章,那么可以通过user.articles就可以获取所有的。但有时候我们不想获取所有的数据,比如只想获取这个作者今天发表的文章,那么这时候我们可以给relationship传递一个lazy='dynamic',以后通过user.articles获取到的就不是一个列表,而是一个AppenderQuery对象了。这样就可以对这个对象再进行一层过滤和排序等操作。
    2、通过lazy='dynamic',获取出来的多的那一部分的数据,就是一个AppenderQuery对象了。这种对象既可以添加新数据,也可以跟Query一样,可以再进行一层过滤。
    总而言之一句话:如果你在获取数据的时候,想要对多的那一边的数据再进行一层过滤,那么这时候就可以考虑使用lazy='dynamic'
    3、lazy可用的选项:

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

    class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50),nullable=False) class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    create_time = Column(DateTime,nullable=False,default=datetime.now)
    uid = Column(Integer,ForeignKey("user.id")) author = relationship("User",backref=backref("articles",lazy="dynamic")) def __repr__(self):
    return "<Article(title: %s)>" % self.title """
    Base.metadata.drop_all()
    Base.metadata.create_all() user = User(username='zhilio')
    for x in range(100):
    article = Article(title="title %s" % x)
    article.author = user
    session.add(article)
    session.commit()
    """ from sqlalchemy.orm.collections import InstrumentedList
    from sqlalchemy.orm.dynamic import AppenderQuery
    from sqlalchemy.orm.query import Query
    user = session.query(User).first()
    # 是一个Query对象
    print(user.articles.filter(Article.id > 50).all())
    # 可以继续追加数据进去
    article =Article(title='title 100')
    user.articles.append(article)
    session.commit()

4、group_by

  • 根据某个字段进行分组。比如想要根据性别进行分组,来统计每个分组分别有多少人,那么可以使用以下代码来完成:

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

5、having

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

    result = session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age >= 18).all()
  • 代码示例:

    from sqlalchemy import create_engine,Column,Integer,Float,Boolean,DECIMAL,Enum,Date,DateTime,Time,String,Text,func,and_,or_,ForeignKey,Table
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker,relationship,backref HOSTNAME = '127.0.0.1'
    PORT = ''
    DATABASE = 'first_sqlalchemy'
    USERNAME = 'root'
    PASSWORD = 'root' # dialect+driver://username:password@host:port/database
    DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8mb4".format(username=USERNAME,password=PASSWORD,host=HOSTNAME,port=PORT,db=DATABASE) engine = create_engine(DB_URI) Base = declarative_base(engine) session = sessionmaker(engine)() class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(50),nullable=False)
    age = Column(Integer,default=0)
    gender = Column(Enum("male","female","secret"),default="male") """
    Base.metadata.drop_all()
    Base.metadata.create_all() user1 = User(username='王五',age=17,gender='male')
    user2 = User(username='赵四',age=17,gender='male')
    user3 = User(username="张三",age=18,gender='female')
    user4 = User(username="刘二",age=19,gender='female')
    user5 = User(username="彭一",age=20,gender='female') session.add_all([user1,user2,user3,user4,user5])
    session.commit()
    """ # 每个年龄的人数
    # from sqlalchemy.orm.query import Query
    result = session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age < 18).all()
    print(result)

6、join

  • join概述:

    1. join分为left join(左外连接)和right join(右外连接)以及内连接(等值连接)。
    2. 参考的网页:http://www.jb51.net/article/15386.htm
    3. 在sqlalchemy中,使用join来完成内连接。在写join的时候,如果不写join的条件,那么默认将使用外键来作为条件连接。
    4. query查找出来什么值,不会取决于join后面的东西,而是取决于query方法中传了什么参数。就跟原生sql中的select 后面那一个一样。
      比如现在要实现一个功能,要查找所有用户,按照发表文章的数量来进行排序。示例代码如下:
    result = session.query(User,func.count(Article.id)).join(Article).group_by(User.id).order_by(func.count(Article.id).desc()).all()
  • 代码示例:

    #encoding: utf-8
    
    from sqlalchemy import create_engine,Column,Integer,Float,Boolean,DECIMAL,Enum,Date,DateTime,Time,String,Text,func,and_,or_,ForeignKey,Table
    from sqlalchemy.dialects.mysql import LONGTEXT
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker,relationship,backref
    # 在Python3中才有这个enum模块,在python2中没有
    import enum
    from datetime import datetime
    import random HOSTNAME = '127.0.0.1'
    PORT = ''
    DATABASE = 'first_sqlalchemy'
    USERNAME = 'root'
    PASSWORD = 'root' # dialect+driver://username:password@host:port/database
    DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8mb4".format(username=USERNAME,password=PASSWORD,host=HOSTNAME,port=PORT,db=DATABASE) engine = create_engine(DB_URI) Base = declarative_base(engine) session = sessionmaker(engine)() class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(50),nullable=False) def __repr__(self):
    return "<User(username: %s)>" % self.username class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    create_time = Column(DateTime, nullable=False, default=datetime.now)
    uid = Column(Integer,ForeignKey("user.id")) author = relationship("User",backref="articles") def __repr__(self):
    return "<Article(title: %s)>" % self.title """
    Base.metadata.drop_all()
    Base.metadata.create_all() user1 = User(username='zhiliao')
    user2 = User(username='ketang') for x in range(1):
    article = Article(title='title %s' % x)
    article.author = user1
    session.add(article)
    session.commit() for x in range(1,3):
    article = Article(title='title %s' % x)
    article.author = user2
    session.add(article)
    session.commit()
    """ # 找到所有的用户,按照发表的文章数量进行排序
    result = session.query(User,func.count(Article.id)).join(Article).group_by(User.id).order_by(func.count(Article.id).desc()).all()
    print(result) # sql语句:
    # select user.username,count(article.id) from user join article on user.id=article.uid group by user.id order by count(article.id) desc;

7、subquery

  • subquery概述:

    子查询可以让多个查询变成一个查询,只要查找一次数据库,性能相对来讲更加高效一点。不用写多个sql语句就可以实现一些复杂的查询。那么在sqlalchemy中,要实现一个子查询,应该使用以下几个步骤:

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

    from sqlalchemy import create_engine,Column,Integer,Float,Boolean,DECIMAL,Enum,Date,DateTime,Time,String,Text,func,and_,or_,ForeignKey,Table
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker,relationship,backref HOSTNAME = '127.0.0.1'
    PORT = ''
    DATABASE = 'first_sqlalchemy'
    USERNAME = 'root'
    PASSWORD = 'root' # dialect+driver://username:password@host:port/database
    DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8mb4".format(username=USERNAME,password=PASSWORD,host=HOSTNAME,port=PORT,db=DATABASE) engine = create_engine(DB_URI) Base = declarative_base(engine) session = sessionmaker(engine)() class User(Base):
    __tablename__ = 'user'
    id = Column(Integer,primary_key=True,autoincrement=True)
    username = Column(String(50),nullable=False)
    city = Column(String(50),nullable=False)
    age = Column(Integer,default=0) def __repr__(self):
    return "<User(username: %s)>" % self.username """
    Base.metadata.drop_all()
    Base.metadata.create_all() user1 = User(username='李A',city="长沙",age=18)
    user2 = User(username='王B',city="长沙",age=18)
    user3 = User(username='赵C',city="北京",age=18)
    user4 = User(username='张D',city="长沙",age=20) session.add_all([user1,user2,user3,user4])
    session.commit()
    """ # 寻找和李A这个人在同一个城市,并且是同年龄的人
    user = session.query(User).filter(User.username=='李A').first()
    users = session.query(User).filter(User.city==user.city,User.age==user.age).all()
    print(users) # 子查询
    stmt = session.query(User.city.label("city"),User.age.label("age")).filter(User.username=='李A').subquery()
    result = session.query(User).filter(User.city==stmt.c.city,User.age==stmt.c.age).all()
    print(result)

SQLAlchemy(四):SQLAlchemy查询高级的更多相关文章

  1. SQLAlchemy04 /SQLAlchemy查询高级

    SQLAlchemy04 /SQLAlchemy查询高级 目录 SQLAlchemy04 /SQLAlchemy查询高级 1.排序 2.limit.offset和切片操作 3.懒加载 4.group_ ...

  2. 第四章 MySQL高级查询(二)

    第四章 MySQL高级查询(二) 一.EXISTS子查询 在执行create 或drop语句之前,可以使用exists语句判断该数据库对像是否存在,返回值是true或false.除此之外,exists ...

  3. sqlalchemy带条件查询相关应用

    sqlalchemy带条件查询 filter_by与filter filter_by 与filter的区别: 1. filter_by只能取值= filter可以==,!=,>=,<=等多 ...

  4. ElasticSearch第四步-查询详解

    ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearch第三步-中文分词 ElasticSea ...

  5. solr与.net系列课程(四)solr查询参数的讲解与.net如何获取solr数据

    solr与.net系列课程(四)solr查询参数的讲解与.net如何获取solr数据 上一节我们完成了solr连接数据库,细心的朋友会发现一个问题,就是solr其实和语言没有任何关系,配置完成后任何语 ...

  6. 转:arcgis api for js入门开发系列四地图查询

    原文地址:arcgis api for js入门开发系列四地图查询 arcgis for js的地图查询方式,一般来说,总共有三种查询方式:FindTask.IdentifyTask.QueryTas ...

  7. MySQL之多表查询一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习

    MySQL之多表查询 阅读目录 一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习 一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 首先说一下,我们写项目一般都会建 ...

  8. T-SQL查询高级--理解SQL SERVER中非聚集索引的覆盖,连接,交叉和过滤

      写在前面:这是第一篇T-SQL查询高级系列文章.但是T-SQL查询进阶系列还远远没有写完.这个主题放到高级我想是因为这个主题需要一些进阶的知识作为基础..如果文章中有错误的地方请不吝指正.本篇文章 ...

  9. 实验四 数据查询3-group by等

    实验四 数据库查询 一.  实验内容: 1. Group by语句 2. Having 语句 3. Order by语句 4. Limit语句 5. Union语句 6. Handler语句 二.  ...

随机推荐

  1. PHP 实现过滤参数字符的方法

    //参数处理函数2function RepPostVar2($val){ if($val!=addslashes($val)) { exit(); } if(substr($val,-1)==&quo ...

  2. flutter pdf 文件浏览

    说明 flutter_full_pdf_viewer 可以实现从网络上下载 pdf 文件并且显示出来. 包地址:flutter_full_pdf_viewer: ^1.0.6 使用方法 1.在 pub ...

  3. mysql忘记root密码后,重新设置、修改root密码

    大致步骤如下(这个步骤针对5.7版本,8.0之后版本修改方式有所改变,版本为8.0之后的可自行搜索相关修改方法) 1. 关闭正在运行的mysql服务,确保mysql服务要先关闭2. 打开dos窗口,转 ...

  4. OO第四单元——终章

    一.架构设计 这一单元的作业主要是围绕UML来对我们的面向对象思维进行训练,刚开始接触的时候或许因为些许陌生而觉得有一定难度,但随着一次一次的代码阅读再加上思考,逐渐地也变得得心应手了起来. 1.第一 ...

  5. EOS基础全家桶(十三)智能合约基础

    简介 智能合约是现在区块链的一大特色,而不同的链使用的智能合约的虚拟机各不相同,编码语言也有很大差异.而今天我们开始学习EOS的智能合约,我也是从EOS初期一直开发合约至今,期间踩过无数坑,也在Sta ...

  6. Python编程快速上手 让繁琐工作自动化 - 专业程序员的养成完整版PDF免费下载_百度云盘

    Python编程快速上手  让繁琐工作自动化 - 专业程序员的养成完整版PDF免费下载_百度云盘 提取码:7qm4 有关本书 累计销售超过10万册 零基础编程者的不二之选 基于Python3编写 通用 ...

  7. Domain Adaptive Faster R-CNN:经典域自适应目标检测算法,解决现实中痛点,代码开源 | CVPR2018

    论文从理论的角度出发,对目标检测的域自适应问题进行了深入的研究,基于H-divergence的对抗训练提出了DA Faster R-CNN,从图片级和实例级两种角度进行域对齐,并且加入一致性正则化来学 ...

  8. js Date format(日期格式化:yyyy-MM-dd HH:mm:ss.S)

    今天在做日期显示的时候,那个显示格式困扰了很久,各种组件都尝试了,总是不如意,最后自己网上找了一个,然后稍微修改一下,感觉这个Util挺常用的,这里mark一下 Date.prototype.form ...

  9. 尚硅谷maven视频教程笔记

    07.尚硅谷_Maven_部署Maven核心程序.avi 第一步先安装jdk 第二步下载maven 特别需要注意的是maven不能存储在有中文和空格的目录下面 3.调试是否安装成功,在cmd中输入 m ...

  10. 信息收集-DNS

    首先更正一个小白很普遍的错误观点,www.baidu.com(严格上是www.baidu.com. 这个点是根的意思,所有的记录从这里开始)并不是一个真正意义上的域名,而是百度服务器的A记录,baid ...