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

相关推荐
智算菩萨11 小时前
【OpenGL】10 完整游戏开发实战:基于OpenGL的2D/3D游戏框架、物理引擎集成与AI辅助编程指南
人工智能·python·游戏·3d·矩阵·pygame·opengl
azhou的代码园12 小时前
基于SpringBoot+微信小程序的图片识别科普系统
spring boot·后端·微信小程序
Tony Bai12 小时前
Rust 看了流泪,AI 看了沉默:扒开 Go 泛型最让你抓狂的“残疾”类型推断
开发语言·人工智能·后端·golang·rust
用户31673613034212 小时前
javaLangchain4j从官方文档入手,看他做了什么——具体使用(二)
后端
無名路人12 小时前
Zsh 脚本 + VS Code 任务:NestJS + Vue3 一键部署到 1Panel
运维·后端·自动化运维
jason成都12 小时前
IoT 设备监控系统实战:基于 EMQX 的 MQTT 连接监控与数据格式指纹识别
开发语言·python
愤豆13 小时前
05-Java语言核心-语法特性--模块化系统详解
java·开发语言·python
ybwycx13 小时前
springboot之集成Elasticsearch
spring boot·后端·elasticsearch
AI-Ming13 小时前
程序员转行学习 AI 大模型: 踩坑记录:服务器内存不够,程序被killed
服务器·人工智能·python·gpt·深度学习·学习·agi
2401_8735449213 小时前
使用Python处理计算机图形学(PIL/Pillow)
jvm·数据库·python