SQLAlchemy 中的 func 函数使用指南

func 是 SQLAlchemy 中用于调用 SQL 函数的关键工具,它允许你在查询中使用数据库的各种内置函数。

基本介绍

func 是 sqlalchemy.sql.functions 模块中的一个特殊对象,它作为 SQL 函数的命名空间使用。当你访问 func 的属性时,SQLAlchemy 会创建一个对应的 SQL 函数调用。

常用函数示例

1. 聚合函数

python 复制代码
from sqlalchemy import func
from models import User, Session

session = Session()

# 计数
total_users = session.query(func.count(User.id)).scalar()

# 求和
total_salary = session.query(func.sum(User.salary)).filter(User.department == 'IT').scalar()

# 平均值
avg_age = session.query(func.avg(User.age)).scalar()

# 最大值/最小值
max_salary = session.query(func.max(User.salary)).scalar()
min_age = session.query(func.min(User.age)).scalar()

2. 字符串函数

python 复制代码
# 字符串连接
session.query(func.concat(User.first_name, ' ', User.last_name).label('full_name')).all()

# 小写转换
session.query(func.lower(User.username)).all()

# 子字符串
session.query(func.substr(User.email, 1, 5)).all()

# 字符串长度
session.query(func.length(User.address)).all()

3. 日期时间函数

python 复制代码
from datetime import datetime

# 当前日期时间
session.query(func.now()).scalar()

# 提取年份
session.query(func.extract('year', User.created_at)).all()

# 日期格式化
session.query(func.strftime('%Y-%m-%d', User.birth_date)).all()

# 日期差
session.query(func.datediff('day', User.start_date, User.end_date)).all()

4. 数学函数

python 复制代码
# 随机数
session.query(User).order_by(func.random()).first()  # PostgreSQL/SQLite
session.query(User).order_by(func.rand()).first()    # MySQL

# 绝对值
session.query(func.abs(User.balance)).all()

# 四舍五入
session.query(func.round(User.score, 2)).all()

# 平方根
session.query(func.sqrt(User.area)).all()

5. 条件表达式

python 复制代码
# CASE WHEN 表达式
session.query(
    func.case(
        [(User.age < 18, 'minor'),
         (User.age >= 18, 'adult')],
        else_='unknown'
    ).label('age_group')
).all()

# COALESCE (返回第一个非NULL值)
session.query(func.coalesce(User.nickname, User.first_name)).all()

# NULLIF (两值相等返回NULL)
session.query(func.nullif(User.salary, 0)).all()

高级用法

1. 函数组合

python 复制代码
# 计算每个用户邮箱域名的长度
session.query(
    func.length(
        func.substr(
            User.email,
            func.instr(User.email, '@') + 1
        )
    )
).all()

2. 自定义函数标签

python 复制代码
# 为函数结果指定列名
session.query(
    func.upper(User.last_name).label('last_name_upper'),
    func.lower(User.first_name).label('first_name_lower')
).all()

3. 分组中使用函数

python 复制代码
# 按年份统计用户数量
session.query(
    func.extract('year', User.created_at).label('year'),
    func.count(User.id).label('user_count')
).group_by('year').all()

4. 窗口函数

python 复制代码
from sqlalchemy import over

# 计算每个部门的薪资排名
session.query(
    User.name,
    User.salary,
    func.rank().over(
        order_by=User.salary.desc(),
        partition_by=User.department
    ).label('rank')
).all()

数据库特定函数

SQLAlchemy 可以透明地处理不同数据库的函数差异:

python 复制代码
# 处理不同数据库的日期差异计算
if dialect.name == 'postgresql':
    age_expr = func.age(User.end_date, User.start_date)
elif dialect.name == 'mysql':
    age_expr = func.timestampdiff('day', User.start_date, User.end_date)
else:
    age_expr = func.julianday(User.end_date) - func.julianday(User.start_date)

自定义函数

你还可以注册和使用自定义SQL函数:

python 复制代码
from sqlalchemy import create_engine
from sqlalchemy.sql.expression import FunctionElement
from sqlalchemy.ext.compiler import compiles

# 定义自定义函数类
class my_random(FunctionElement):
    type = Numeric()
    name = 'my_random'

# 定义编译规则
@compiles(my_random, 'postgresql')
def compile_my_random_postgresql(element, compiler, **kw):
    return "my_random()"  # 调用PostgreSQL中的自定义函数

# 使用自定义函数
session.query(User).order_by(my_random()).limit(5).all()

注意事项

  1. func 生成的是 SQL 函数表达式,不是 Python 函数调用
  2. 不同数据库支持的函数可能不同,SQLAlchemy 会尽量处理这些差异
  3. 复杂的函数组合可能会影响查询性能
  4. 在可能的情况下,考虑使用 SQLAlchemy 的核心表达式而不是原始 SQL 函数

通过 func,可以充分利用数据库的强大功能,同时保持代码的数据库无关性。

相关推荐
ragnwang9 小时前
Notes: Python pybind11 import C++ module
开发语言·c++·python
王中阳Go9 小时前
后端转 Agent 岗面试怎么答:8 个高频问题与应答口径
人工智能·后端·python·大语言模型
weixin_3077791310 小时前
RAG 面试陷阱——混合检索并非无条件优越:一个条件反转实验
人工智能·python·面试·职场和发展
云和数据.ChenGuang11 小时前
深入解析 Python 的 dir():从用法到 CPython 源码实现
开发语言·人工智能·python·langchain
荣码13 小时前
长上下文与大文档处理:200页PDF怎么喂给AI,我踩了4个坑
java·python
databook14 小时前
Pandas 与 Polars:语法、性能和资源占用方面的对比
python·数据分析·pandas
威哥爱编程14 小时前
Python 智能体开发实战 10:本地跑得好好的,一并发就崩?把它做成一个能上线的服务
python·agent
威哥爱编程14 小时前
Python 智能体开发实战 09:改了提示词,到底是变好还是变坏?搭一套能打分的离线评测
python·agent
meiying883815 小时前
多快递公司快递单号批量查询接口怎么对接?Python 聚合查询实现
java·大数据·python
Hello_Pyhx15 小时前
Deep-Live-Cam 源码配置思路:环境、模型与执行后端分开排查
python