簡體   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