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中最常用的排序方法,你可以根据具体需求选择合适的方案。

相关推荐
流浪克拉玛依1 小时前
Go Web 服务限流器实战:从原理到压测验证 --使用 Gin 框架 + Uber Ratelimit / 官方限流器,并通过 Vegeta 进行性能剖析
后端
Flittly2 小时前
【从零手写 ClaudeCode:learn-claude-code 项目实战笔记】(3)TodoWrite (待办写入)
python·agent
孟沐2 小时前
保姆级教程:手写三层架构 vs MyBatis-Plus
后端
星浩AI2 小时前
让模型自己写 Skills——从素材到自动生成工作流
人工智能·后端·agent
华仔啊4 小时前
为啥不用 MP 的 saveOrUpdateBatch?MySQL 一条 SQL 批量增改才是最优解
java·后端
武子康5 小时前
大数据-242 离线数仓 - DataX 实战:MySQL 全量/增量导入 HDFS + Hive 分区(离线数仓 ODS
大数据·后端·apache hive
砍材农夫5 小时前
TCP和UDP区别
后端
千寻girling6 小时前
一份不可多得的 《 Django 》 零基础入门教程
后端·python·面试
千寻girling6 小时前
Python 是用来做 AI 人工智能 的 , 不适合开发 Web 网站 | 《Web框架》
人工智能·后端·算法
贾铭6 小时前
如何实现一个网页版的剪映(三)使用fabric.js绘制时间轴
前端·后端