SQLAlchemy各种排序示例

1. 基础排序

简单单字段排序

python 复制代码
from sqlalchemy import create_engine, Column, Integer, String, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from datetime import datetime

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    age = Column(Integer)
    create_time = Column(DateTime)

# 查询并排序
# 升序
users = session.query(User).order_by(User.age).all()

# 降序
users = session.query(User).order_by(User.age.desc()).all()

# 或者使用负号(仅适用于数字)
users = session.query(User).order_by(-User.age).all()

2. 多字段排序

python 复制代码
# 先按年龄升序,再按创建时间降序
users = session.query(User)\
    .order_by(User.age, User.create_time.desc())\
    .all()

# 另一种写法
from sqlalchemy import desc
users = session.query(User)\
    .order_by(User.age, desc(User.create_time))\
    .all()

3. 使用文本SQL排序

python 复制代码
from sqlalchemy import text

# 直接使用SQL语句
users = session.query(User)\
    .order_by(text("age desc, create_time"))\
    .all()

# 带参数的文本排序
users = session.query(User)\
    .order_by(text("age :sort_order"), text("name"))\
    .params(sort_order='desc')\
    .all()

4. 关联表排序

python 复制代码
class Post(Base):
    __tablename__ = 'posts'
    
    id = Column(Integer, primary_key=True)
    title = Column(String(100))
    user_id = Column(Integer, ForeignKey('users.id'))
    user = relationship("User")

# 按关联表的字段排序
posts = session.query(Post)\
    .join(Post.user)\
    .order_by(User.name.asc(), Post.title)\
    .all()

5. 表达式排序

python 复制代码
from sqlalchemy import func

# 按计算字段排序
users = session.query(User)\
    .order_by(func.length(User.name))\
    .all()

# 按条件排序(CASE WHEN)
from sqlalchemy import case
users = session.query(User)\
    .order_by(
        case(
            [(User.age < 18, 1),  # 未成年人排前面
             (User.age >= 60, 2),  # 老年人其次
             else_=3]             # 其他最后
        )
    )\
    .all()

6. NULL值排序

python 复制代码
# NULLS FIRST / NULLS LAST
from sqlalchemy import nullsfirst, nullslast

# 将NULL值排在最后
users = session.query(User)\
    .order_by(nullslast(User.age))\
    .all()

# 将NULL值排在最前
users = session.query(User)\
    .order_by(nullsfirst(User.age))\
    .all()

# 结合升降序
users = session.query(User)\
    .order_by(nullslast(User.age.desc()))\
    .all()

7. 动态排序

python 复制代码
def get_users(sort_by='id', sort_order='asc'):
    query = session.query(User)
    
    # 根据传入参数动态排序
    if sort_order.lower() == 'desc':
        query = query.order_by(getattr(User, sort_by).desc())
    else:
        query = query.order_by(getattr(User, sort_by))
    
    return query.all()

# 使用示例
users = get_users('age', 'desc')

8. 分页排序

python 复制代码
# 排序后分页
page = 1
page_size = 20

users = session.query(User)\
    .order_by(User.create_time.desc())\
    .limit(page_size)\
    .offset((page - 1) * page_size)\
    .all()

9. 完整示例

python 复制代码
from sqlalchemy import create_and, Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
from sqlalchemy import desc, func, text

Base = declarative_base()

class Department(Base):
    __tablename__ = 'departments'
    
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    employees = relationship("Employee", back_populates="department")

class Employee(Base):
    __tablename__ = 'employees'
    
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    age = Column(Integer)
    salary = Column(Integer)
    department_id = Column(Integer, ForeignKey('departments.id'))
    hire_date = Column(DateTime, default=datetime.now)
    
    department = relationship("Department", back_populates="employees")

# 复杂排序示例
def complex_sort_example(session):
    # 按部门名称、入职时间、工资降序排序
    employees = session.query(Employee)\
        .join(Employee.department)\
        .order_by(
            Department.name,
            Employee.hire_date.desc(),
            Employee.salary.desc()
        )\
        .all()
    
    # 按工资等级排序
    employees = session.query(Employee)\
        .order_by(
            case(
                [(Employee.salary >= 10000, 1),   # 高薪
                 (Employee.salary >= 5000, 2),    # 中薪
                 else_=3]                        # 低薪
            ),
            Employee.hire_date.desc()
        )\
        .all()
    
    return employees

注意事项

  1. 性能优化:对大量数据排序时,确保排序字段有索引
  2. NULL值处理:注意不同数据库对NULL值的默认排序规则不同
  3. 表达式排序:复杂表达式可能影响查询性能
  4. 关联表排序:记得添加必要的join操作

这些是SQLAlchemy中最常用的排序方法,你可以根据具体需求选择合适的方案。

相关推荐
65岁退休Coder6 小时前
LangChain v1.3.4 笔记 - 07 补充:链式调用 LCEL
后端·python·langchain
卷无止境7 小时前
FastAPI 部署在 Nginx 后面到底该怎么配
后端·python
码流怪侠7 小时前
用 WiFi 信号数人头:howmanypeoplearearound 项目深度解析
后端·开源·github
半亩码田7 小时前
C#转Python第3.1篇:Python 的 class 没有访问修饰符?面向对象的另一条路
开发语言·python·c#
心运软件7 小时前
SpringBoot+ Vue校园社团管理平台的完整架构设计
vue.js·后端
Wzx1980128 小时前
python沙箱和docker沙箱你选对了吗?
开发语言·python·docker
Python私教8 小时前
签名 URL 刷新导致审批失效?别急着删掉所有 query
python·安全
Jodie同志8 小时前
第16~23天:持久化、HITL、流式、MCP与安全
前端·后端·agent
牧羊人.3338 小时前
Python 办公自动化从入门到入土|09 数据容器之字典
开发语言·python
Jodie同志8 小时前
第1~15天:原生Agent、RAG与LangGraph基础(完整代码实操)
前端·后端·agent