Python全栈之Flask框架之ORM排序、分页、高级查询和子查询

一、数据库排序

在ORM中排序的方式有2种:

  • order_by()
    在查询结果时,使用order_by()方法,可以指定根据表中的某个字段进行排序。
  • 模型定义时声明
    有时候,不想每次在查询的时候都指定排序的方式,可以在定义模型的时候就指定默认排序的方式。

默认情况下是升序,还可以指定按降序方式输出结果。

生成数据:

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)


Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

for i in range(10):
    article = Article(title='Title %d' % i, length=randint(100, 10000))
    session.add(article)

session.commit()

运行后即插入数据。

此时用order_by()方法对查询结果排序,测试如下:

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

articles = session.query(Article).order_by(Article.length).all()
for article in articles:
    print(article)

打印:

User(id: 4, name: Title 3, length: 143)
User(id: 6, name: Title 5, length: 1079)
User(id: 3, name: Title 2, length: 1323)
User(id: 7, name: Title 6, length: 1589)
User(id: 1, name: Title 0, length: 1604)
User(id: 2, name: Title 1, length: 2187)
User(id: 8, name: Title 7, length: 2933)
User(id: 10, name: Title 9, length: 3556)
User(id: 5, name: Title 4, length: 3829)
User(id: 9, name: Title 8, length: 8520)

显然,是按length属性从小到大排列的,也可以得到order_by()方法默认是升序排序。

如果想要降序排列,可以采用如下两种方式:

  • 使用desc()方法
order_by(Article.length.desc()).all()
  • 字段前面加符号-
order_by(-Article.length).all()

其一测试如下:

扫描二维码关注公众号,回复: 11151107 查看本文章
from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

articles = session.query(Article).order_by(Article.length.desc()).all()
for article in articles:
    print(article)

打印:

User(id: 9, name: Title 8, length: 8520)
User(id: 5, name: Title 4, length: 3829)
User(id: 10, name: Title 9, length: 3556)
User(id: 8, name: Title 7, length: 2933)
User(id: 2, name: Title 1, length: 2187)
User(id: 1, name: Title 0, length: 1604)
User(id: 7, name: Title 6, length: 1589)
User(id: 3, name: Title 2, length: 1323)
User(id: 6, name: Title 5, length: 1079)
User(id: 4, name: Title 3, length: 143)

这是通过在查询结果时使用order_by()方法来实现的,如果要想在查询时就默认以某一种方式排序,可以在建立模型时定义,如下:

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)

    __mapper_args__ = {
        'order_by':length
    }


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

articles = session.query(Article).all()
for article in articles:
    print(article)

输出与之前默认升序一样的结果,显然此时不再需要在查询时使用order_by()方法,还可以降序,如下:

__mapper_args__ = {
	'order_by':length.desc()
}

__mapper_args__ = {
	'order_by':-length
}

显然,在定义模型时就定义默认排序更好,因为如果在查询时再定义排序,会降低查询效率。

二、limit、offset和切片

  • limit
    指定返回行的最大记录数目。
  • offset
    指定第一个返回记录行的偏移量。
  • 切片
    对Query对象使用切片操作,来获取想要的数据。

limit测试:

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)

    __mapper_args__ = {
        'order_by':length
    }


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()


articles = session.query(Article).limit(3).all()
for article in articles:
    print(article)

打印:

User(id: 9, name: Title 8, length: 1895)
User(id: 1, name: Title 0, length: 2038)
User(id: 7, name: Title 6, length: 2456)

显然,此时只查询了前3条数据。

offset测试:

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)

    __mapper_args__ = {
        'order_by':length
    }


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()


articles = session.query(Article).offset(3).limit(3).all()
for article in articles:
    print(article)

打印:

User(id: 3, name: Title 2, length: 4884)
User(id: 6, name: Title 5, length: 5197)
User(id: 8, name: Title 7, length: 8874)

上面查询了从第4条开始的连续3条数据;
显然,offset的参数是从0开始计数的。

还可以多个查询条件同时使用:

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()


articles = session.query(Article).order_by(Article.length.desc()).offset(3).limit(3).all()
for article in articles:
    print(article)

打印:

User(id: 5, name: Title 4, length: 8897)
User(id: 8, name: Title 7, length: 8874)
User(id: 6, name: Title 5, length: 5197)

只能先用order_by()排序,再用limit()offset()取数据,而不能颠倒两者的顺序。

切片测试如下:

from sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import randint

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class Article(Base):
    __tablename__ = 'article'
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=False)
    length = Column(Integer)

    def __str__(self):
        return 'User(id: {}, name: {}, length: {})'.format(self.id, self.title, self.length)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()


articles = session.query(Article).all()[2:5]
for article in articles:
    print(article)

打印:

User(id: 3, name: Title 2, length: 4884)
User(id: 4, name: Title 3, length: 9693)
User(id: 5, name: Title 4, length: 8897)

limit()和切片都可以截取部分数据,其区别在于:
limit()是在查询时就限定了查询的结果,即查询的结果并不包括所有结果,而是指定的部分;
而切片是现将所有符合的结果查询出来,得到的是一个列表,再对列表切片;
显然,用limit()方法的效率更高。

三、高级查询和子查询

1.group_by

group_by()指定根据某个字段分组。

创建数据库表并添加数据:

from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import *

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


def generate_random_str(randomlength=6):
    '''生成指定长度的随机字符串'''
    random_str = ''
    base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
    length = len(base_str) - 1
    for i in range(randomlength):
        random_str += base_str[randint(0, length)]
    return random_str


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    gender = Column(Enum('男', '女'))
    age = Column(Integer)

    def __str__(self):
        return 'User(id: {}, username: {}, gender: {}, age: {})'.format(self.id, self.username, self.gender, self.age)


Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()


for _ in range(20):
    user = User(username=generate_random_str(), gender=choice(['男', '女']), age=randint(5, 40))
    session.add(user)

session.commit()

group_by()进行查询:

from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from random import *

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    gender = Column(Enum('男', '女'))
    age = Column(Integer)

    def __str__(self):
        return 'User(id: {}, username: {}, gender: {}, age: {})'.format(self.id, self.username, self.gender, self.age)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

results = session.query(User.gender).group_by(User.gender).all()
for result in results:
    print(result)

打印:

('男',)
('女',)

很显然,query()group_by()的参数所包含的字段要保持一致。

可以对每个类别进行计数,如下:

from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy import create_engine, func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    gender = Column(Enum('男', '女'))
    age = Column(Integer)

    def __str__(self):
        return 'User(id: {}, username: {}, gender: {}, age: {})'.format(self.id, self.username, self.gender, self.age)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

results = session.query(User.gender, func.count(User.id)).group_by(User.gender).all()
for result in results:
    print(result)

打印:

('男', 12)
('女', 8)

显然,查到了性别为男、女的人数。

2.having

having()对通过group_by()分类后的结果进一步过滤。
显然,having()中的字段也应该与group_by()中的字段保持一致。

根据年龄分组后再根据年龄条件过滤:

from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy import create_engine, func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    gender = Column(Enum('男', '女'))
    age = Column(Integer)

    def __str__(self):
        return 'User(id: {}, username: {}, gender: {}, age: {})'.format(self.id, self.username, self.gender, self.age)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

results = session.query(User.age, func.count(User.id)).group_by(User.age).having(User.age > 18).all()
for result in results:
    print(result)

打印:

(20, 1)
(21, 2)
(22, 1)
(32, 1)
(34, 1)
(36, 1)
(39, 3)

显然,得到了大于18的各个年龄阶段的人数。

3.子查询

MySQL中有子查询,SQLAlchemy也支持子查询,一般过程是先构造子查询,再将子查询放到父查询中。

构造数据:

from random import *
from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


def generate_random_str(randomlength=6):
    '''生成指定长度的随机字符串'''
    random_str = ''
    base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
    length = len(base_str) - 1
    for i in range(randomlength):
        random_str += base_str[randint(0, length)]
    return random_str


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    gender = Column(Enum('男', '女'))
    age = Column(Integer)
    city = Column(Enum('Beijing', 'New York', 'London', 'Paris', 'Tokyo'))

    def __str__(self):
        return 'User(id: {}, username: {}, gender: {}, age: {}, city: {})'.format(self.id, self.username, self.gender, self.age, self.city)


Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

for _ in range(50):
    user = User(username=generate_random_str(), gender=choice(['男', '女']), age=randint(5, 40), city=choice(['Beijing', 'New York', 'London', 'Paris', 'Tokyo']))
    session.add(user)

session.commit()

运行即创建数据成功。

现在有一个需求,查询和id为3的user在同一个城市的user,可以先用一条语句查询出id为3的用户所在的城市,然后再根据城市进行第二次查询:

from random import *
from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    gender = Column(Enum('男', '女'))
    age = Column(Integer)
    city = Column(Enum('Beijing', 'New York', 'London', 'Paris', 'Tokyo'))

    def __str__(self):
        return 'User(id: {}, username: {}, gender: {}, age: {}, city: {})'.format(self.id, self.username, self.gender, self.age, self.city)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

user = session.query(User).filter(User.id == 3).first()
results = session.query(User).filter(User.city == user.city).all()
for result in results:
    print(result)

打印:

User(id: 3, username: gTq26G, gender:, age: 8, city: Paris)
User(id: 10, username: h7hs1d, gender:, age: 35, city: Paris)
User(id: 14, username: xmbm6H, gender:, age: 31, city: Paris)
User(id: 20, username: Gq0AlG, gender:, age: 39, city: Paris)
User(id: 25, username: ksGOnY, gender:, age: 32, city: Paris)
User(id: 27, username: H8Amxe, gender:, age: 34, city: Paris)
User(id: 28, username: 9Vmt4P, gender:, age: 9, city: Paris)
User(id: 31, username: rM3Qoe, gender:, age: 20, city: Paris)
User(id: 32, username: 1XEtX3, gender:, age: 35, city: Paris)
User(id: 33, username: 3ZzS4b, gender:, age: 13, city: Paris)
User(id: 34, username: naCdU4, gender:, age: 35, city: Paris)
User(id: 35, username: iG7Yfp, gender:, age: 27, city: Paris)
User(id: 36, username: 12kwgW, gender:, age: 34, city: Paris)
User(id: 37, username: Dwl6Ba, gender:, age: 18, city: Paris)
User(id: 47, username: ehe80s, gender:, age: 7, city: Paris)
User(id: 50, username: MdxxLe, gender:, age: 33, city: Paris)

显然,打印出了所有符合条件的结果,但是这是多个语句查询出的,显得很麻烦,可以用子查询,如下:

from sqlalchemy import Column, Integer, String, Enum
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 数据库连接配置
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DATABASE = 'flask_orm'
DB_URL = 'mysql+mysqlconnector://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

engine = create_engine(DB_URL)
Base = declarative_base(engine)


class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), nullable=False)
    gender = Column(Enum('男', '女'))
    age = Column(Integer)
    city = Column(Enum('Beijing', 'New York', 'London', 'Paris', 'Tokyo'))

    def __str__(self):
        return 'User(id: {}, username: {}, gender: {}, age: {}, city: {})'.format(self.id, self.username, self.gender, self.age, self.city)


# Base.metadata.drop_all()
Base.metadata.create_all()

Session = sessionmaker(bind=engine)
session = Session()

sub = session.query(User.city.label('city')).filter(User.id == 3).subquery()
results = session.query(User).filter(User.city == sub.c.city).all()
for result in results:
    print(result)

可以看到,一个查询如果想要变为子查询,需要通过subquery()方法实现,变成子查询后,通过子查询.c属性来访问查询出来的列。

原创文章 124 获赞 1318 访问量 32万+

猜你喜欢

转载自blog.csdn.net/CUFEECR/article/details/105813112
今日推荐