首页 > 解决方案 > 在单个 SQLAlchemy 查询中选择函数和表列

问题描述

我做了一些搜索,但找不到任何示例。

有没有办法在使用 SQLAlchemy Core 时表和函数调用中查询多个列?

这是我想要实现的查询:

SELECT
    t.id, t.field_1, t.field_2,
    some_function(t.field_2, t.field_3).*
FROM my_table t

哪里是一个返回三元组的some_function函数,比如说calc_field_1calc_field_2calc_field_3

结果集应该是这样的表:

ID 字段_1 字段_2 calc_field_1 calc_field_2 calc_field_3
1 ... ... ... ... ...
2 ... ... ... ... ...
3 ... ... ... ... ...

标签: pythonsqlalchemy

解决方案


如果可以将原始 SQL 更改为此

SELECT
    t.id, t.field_1, t.field_2,
    calc_field_1, calc_field_2, calc_field_3
FROM my_table t, some_function(t.field_2, t.field_3);

然后可以在 Sqlalchemy Core 上表达

stmt = (
    select([
        my_table.c.id,
        my_table.c.field_1,
        my_table.c.field_2,
        column('calc_field_1'),
        column('calc_field_2'),
        column('calc_field_3')
    ])
    .select_from(my_table)
    .select_from(func.some_function(my_table.c.field_2, my_table.c.field_3))
)

目前(从 Sqlalchemy 1.3 开始)文档建议在这里. Sqlalchemy 1.4(测试版)应该提供表值函数


如果您不能将函数移动到 -FROM子句,那么..

from sqlalchemy import literal_column
from sqlalchemy.sql.expression import Grouping
stmt = (
    select([
        my_table.c.id,
        my_table.c.field_1,
        my_table.c.field_2,
        Grouping(
            func.some_function(my_table.c.field_2, my_table.c.field_3)
        ).op('.')(literal_column('calc_field_1')).label('calc_field_1'),
        Grouping(
            func.some_function(my_table.c.field_2, my_table.c.field_3)
        ).op('.')(literal_column('calc_field_2')).label('calc_field_2'),
        Grouping(
            func.some_function(my_table.c.field_2, my_table.c.field_3)
        ).op('.')(literal_column('calc_field_3')).label('calc_field_3'),
    ])
    .select_from(my_table)
)

它将产生以下 SQL

SELECT t.id, t.field_1, t.field_2,
  (some_function(t.field_2, t.field_3)) . calc_field_1 AS calc_field_1,
  (some_function(t.field_2, t.field_3)) . calc_field_2 AS calc_field_2,
  (some_function(t.field_2, t.field_3)) . calc_field_3 AS calc_field_3
FROM my_table t

和一个速记操作:

from sqlalchemy.sql import functions

class some_function(functions.GenericFunction):
    def __getitem__(self, key):
        return Grouping(self).op('.')(column(key, String))

stmt = (
    select([
        my_table.c.id,
        my_table.c.field_1,
        my_table.c.field_2,
        some_function(my_table.c.field_1, my_table.c.field_2)['calc_field_1'].label('calc_field_1'),
        some_function(my_table.c.field_1, my_table.c.field_2)['calc_field_2'].label('calc_field_2'),
        some_function(my_table.c.field_1, my_table.c.field_2)['calc_field_3'].label('calc_field_3'),
    ])
    .select_from(my_table)
)

解决方案取自这里,用 postgresql 检查


推荐阅读