繁体   English   中英

PgSQL function 返回表和过程中计算的额外数据

[英]PgSQL function returning table and extra data computed in process

在 PgSQL 中,我制作了巨大的 select,然后我想计算它的大小并应用一些额外的过滤器。 执行两次听起来很愚蠢,所以我将它包装在 function 中,然后“缓存”它并在“id”列存储大小的末尾返回过滤表和额外行的联合

with q as (select * from myFunc())
select * from q
where q.distance < 400
union all
select count(*) as id, null,null,null
from q

但它看起来也不是正确的解决方案......

所以问题是:在 pg 中是像“生成器函数”这样的东西还是可以正确解决这个问题的任何其他东西?


postgreSQL 13

myFunc 又名“selectItemsByRootTag”

CREATE OR REPLACE FUNCTION selectItemsByRootTag(
    in tag_name VARCHAR(50)
)
RETURNS table(
    id BIGINT,
    name VARCHAR(50),
    description TEXT,
    /*info JSON,*/
    distance INTEGER
)
AS $$
BEGIN
RETURN QUERY(
    WITH RECURSIVE prod AS (
        SELECT
            tags.name, tags.id, tags.parent_tags
        FROM      
            tags
        WHERE tags.name = (tags_name)
        UNION
        SELECT c.name, c.id , c.parent_tags
        FROM 
            tags as c
            INNER JOIN prod as p
                ON c.parent_tags = p.id
    )
    SELECT
        points.id,
        points.name,
        points.description,
        /*points.info,*/
        points.distance
    from points
    left join tags on points.tag_id = tags.id
    where tags.name in (select prod.name from prod)
);
END;
$$ LANGUAGE plpgsql;

结果,我想看看可能会产生一些中间结果的 2 个表或生成器 function

演示

CREATE OR REPLACE FUNCTION pg_temp.selectitemsbyroottag(tag_name text, _distance numeric)
 RETURNS TABLE(id bigint, name text, description text, distance numeric, count bigint)
 LANGUAGE plpgsql
AS $function$
DECLARE _sql text;
BEGIN
_sql := $p1$WITH RECURSIVE prod AS (
            SELECT
                tags.name, tags.id, tags.parent_tags
            FROM
                tags
            WHERE tags.name ilike '%$p1$ || tag_name || $p2$%'
            UNION
            SELECT c.name, c.id , c.parent_tags
            FROM
                tags as c
                INNER JOIN prod as p
                    ON c.parent_tags = p.id
        )
        SELECT
            points.id,
            points.name,
            points.description,
            points.distance,
            count(*) over ()
        from points
        left join tags on points.tag_id = tags.id
        where tags.name in (select prod.name from prod)
        and points.distance > $p2$ || _distance
    ;
raise notice '_sql: %', _sql;

return query execute _sql;
END;
$function$

您可以通过以下方式调用它

select * from pg_temp.selectItemsByRootTag('test',20);
select * from pg_temp.selectItemsByRootTag('test_8',20) with ORDINALITY;

1.调用function的方式,会有一行total count总行数。 第二种方式调用有行数加上一个序列增量号。

我还将where q.distance < 400设置为 function 输入参数。 selectItemsByRootTag('test',20); 表示q.distance > 20tags.name ilike '%test%'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM