Postgresql 在SQLAlchemy中加入集合返回函数(SRF)和访问列

Postgresql 在SQLAlchemy中加入集合返回函数(SRF)和访问列,postgresql,join,sqlalchemy,Postgresql,Join,Sqlalchemy,假设我有一个活动表和一个订阅表。每个活动都有一个对其他对象的泛型引用数组,每个订阅都有一个对同一集中其他对象的泛型引用 CREATE TABLE activity ( id serial primary key, ob_refs UUID[] not null ); CREATE TABLE subscription ( id UUID primary key, ob_ref UUID, subscribed boolean not null ); 我

假设我有一个
活动
表和一个
订阅
表。每个活动都有一个对其他对象的泛型引用数组,每个订阅都有一个对同一集中其他对象的泛型引用

CREATE TABLE activity (
    id serial primary key,
    ob_refs UUID[] not null
);

CREATE TABLE subscription (
    id UUID primary key,
    ob_ref UUID,
    subscribed boolean not null
);
我想加入set returning函数
unnest
,这样我就可以找到“最深”的匹配订阅,如下所示:

SELECT id
FROM (
    SELECT DISTINCT ON (activity.id)
        activity.id,
        x.ob_ref, x.ob_depth,
        subscription.subscribed IS NULL OR subscription.subscribed = TRUE
            AS subscribed,
    FROM activity

    LEFT JOIN subscription
        ON activity.ob_refs @> array[subscription.ob_ref]

    LEFT JOIN unnest(activity.ob_refs)
        WITH ORDINALITY AS x(ob_ref, ob_depth)
        ON subscription.ob_ref = x.ob_ref

    ORDER BY x.ob_depth DESC
) sub
WHERE subscribed = TRUE;
act_ref = unnest_func(Activity.ob_refs)
query = (query
    .add_columns(act_ref.c.unnest, act_ref.c.ordinality)
    .outerjoin(act_ref, sa.true())
    .outerjoin(Subscription, Subscription.ob_ref == act_ref.c.unnest)
    .order_by(act_ref.c.ordinality.desc()))
但我不知道如何进行第二次连接并访问列。我已尝试创建一个
FromClause

但这将导致此SQL包含另一个子查询:

LEFT OUTER JOIN (
        SELECT unnest AS ob_ref, ordinality AS ref_i
        FROM unnest(activity.ob_refs) WITH ORDINALITY
    ) AS act_ref_t
    ON subscription.ob_refs @> ARRAY[act_ref_t.ob_ref]
。。。由于缺少和
LATERAL
关键字而失败:

表“activity”有一个条目,但不能从查询的这一部分引用它

那么,如何在不使用子查询的情况下为这个SRF创建JOIN子句呢?还是我还遗漏了什么

编辑1使用with而不是
sa。选择
让我更接近:

act_ref_t = (sa.sql.text(
        "unnest(activity.ob_refs) WITH ORDINALITY")
    .columns(sa.column('unnest', UUID),
             sa.column('ordinality', sa.Integer))
    .alias('act_ref'))
但结果SQL失败,因为它将子句包装在括号中:

LEFT OUTER JOIN (unnest(activity.ob_refs) WITH ORDINALITY)
    AS act_ref ON subscription.ob_ref = act_ref.unnest

错误是“
”处或附近的
语法错误。我是否可以从
中获取不包含在括号中的
TextAsFrom?

事实证明,SA并不直接支持这一点,但使用a和a可以实现正确的行为。如中所述的首次导入。然后创建一个特殊的
unnest
函数,该函数包含带有顺序性的
修饰符:

class unnest_func(ColumnFunction):
    name = 'unnest'
    column_names = ['unnest', 'ordinality']

@compiles(unnest_func)
def _compile_unnest_func(element, compiler, **kw):
    return compiler.visit_function(element, **kw) + " WITH ORDINALITY"
然后,您可以在联接、排序等中使用它,如下所示:

SELECT id
FROM (
    SELECT DISTINCT ON (activity.id)
        activity.id,
        x.ob_ref, x.ob_depth,
        subscription.subscribed IS NULL OR subscription.subscribed = TRUE
            AS subscribed,
    FROM activity

    LEFT JOIN subscription
        ON activity.ob_refs @> array[subscription.ob_ref]

    LEFT JOIN unnest(activity.ob_refs)
        WITH ORDINALITY AS x(ob_ref, ob_depth)
        ON subscription.ob_ref = x.ob_ref

    ORDER BY x.ob_depth DESC
) sub
WHERE subscribed = TRUE;
act_ref = unnest_func(Activity.ob_refs)
query = (query
    .add_columns(act_ref.c.unnest, act_ref.c.ordinality)
    .outerjoin(act_ref, sa.true())
    .outerjoin(Subscription, Subscription.ob_ref == act_ref.c.unnest)
    .order_by(act_ref.c.ordinality.desc()))