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 分钟前
LangChain4j 和 LangGraph4j,哪个更好?
后端
SelectDB1 小时前
Apache Doris Python UDF:让 SQL 直接调用 Python 生态,支撑 Agent 时代复杂业务逻辑
大数据·数据库·python
ServBay1 小时前
7 个AI开发中真正用得上的 MCP Server,配合Claude Code食用效果更佳
后端·claude·mcp
妙码生花2 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
用户6757049885022 小时前
Go 语言里判断字符串为空,90% 的人都写错了!
后端·go
用户6757049885022 小时前
Go 进阶必修:90% 的人都没用对的“表驱动法”
后端·go
小兔崽子去哪了2 小时前
Java 生成二维码解决方案
java·后端
苍何2 小时前
懂事的 Agent 已经开始自己看屏幕干活了,效率起飞!
后端
掘金码甲哥3 小时前
1分钟买不了吃亏系列: nginx动态域名解析
后端
神奇小汤圆3 小时前
2026大厂Java岗面试记录:八股+场景+项目+AI,一文讲透快速上岸路径(含答案)
后端