Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从一组条目计算聚合的tsrange?_Sql_Postgresql_Dynamic Programming_Dynamic Sql_Range Types - Fatal编程技术网

Sql 从一组条目计算聚合的tsrange?

Sql 从一组条目计算聚合的tsrange?,sql,postgresql,dynamic-programming,dynamic-sql,range-types,Sql,Postgresql,Dynamic Programming,Dynamic Sql,Range Types,我试图从一组从SQL查询中提取的行中计算聚合的tsrange。问题是,我不断收到输入参数未传入的错误 CREATE OR REPLACE AGGREGATE range_merge(anyrange) ( sfunc = range_merge, stype = anyrange ); DROP FUNCTION IF EXISTS aggregate_validity(entity_name regclass, entry bigint); CREATE OR REPLAC

我试图从一组从SQL查询中提取的行中计算聚合的
tsrange
。问题是,我不断收到输入参数未传入的错误

CREATE OR REPLACE AGGREGATE range_merge(anyrange)
(
    sfunc = range_merge,
    stype = anyrange
);

DROP FUNCTION IF EXISTS aggregate_validity(entity_name regclass, entry bigint);

CREATE OR REPLACE FUNCTION aggregate_validity(entity_name regclass, entry bigint) returns tsrange AS
$$
DECLARE
    result tsrange;
BEGIN
   EXECUTE format('select range_merge(valid) from %s where entity_id = %U', entity_name, entry) into result;
   return result;
END
$$ LANGUAGE plpgsql;
当我这样做时:

select * from aggregate_validity(country, 1);
我收到一个错误,指出实体名称和条目不存在。它似乎没有正确地参数化语句中的输入。

函数:

EXECUTE format('select range_merge(valid) from %s where entity_id=%U',entity_name, entry) 
into result;
=>
EXECUTE format('select range_merge(valid) from %I where entity_id=%s',entity_name, entry) 
into result;
--%I for identifier, %s for value
电话:

电话:

小提琴

调用不需要
SELECT*FROM
,因为函数会为每个定义返回一个值

我使用了一个
OUT
参数来简化(
OUT result tsrange
)。见:

不要将
条目
值连接到SQL字符串中。使用子句将其作为值传递。更干净,更快

由于
entity\u name
作为
regclass
传递,因此可以安全地简单地进行连接(这稍微便宜一点)。见:

另外,Lukasz已经提供了缺少引号和不正确的格式说明符

自定义聚合函数
range\u merge()

  • 我不会将其命名为“range\u merge”,这也是普通函数的名称。虽然这是合法的,但它仍然会带来令人困惑的错误

  • 您知道函数
    range\u merge()
    包含输出范围中输入范围之间的间隙吗

  • range\u merge()
    为任何空输入返回空值。因此,如果表的
    valid
    列中有任何空值,则结果总是空的。我强烈建议将任何涉及的列定义为
    非空

  • 如果你有权安装额外的模块,请考虑Paul Jungwirth。它提供了高级函数

    range\u agg()
    来解决上述一些问题

    如果你不想包含空白,考虑一下

    我可能根本不会使用
    aggregate\u validity()
    。它模糊了Postgres查询计划器的嵌套功能,并可能导致次优的查询计划。通常,您可以将其替换为相关或
    横向子查询
    子查询
    ,Postgres可以在外部查询的上下文中对其进行规划和优化。我在小提琴上附加了一个演示:

    小提琴

    相关的:


    是否在select语句中执行嵌套的select语句?我有点困惑如何做
    国家
    不起作用选择聚合有效性(“国家”,1)<代码>国家/地区
    被视为text@kafka:我添加了一些关于如何使用子查询的详细信息。另外,
    选择聚合有效期(“国家”,1)
    应该可以正常工作,正如在两个小提琴中所演示的那样。请注意,
    'country'
    在这里是一个非类型化的字符串文本。如果传递类型为
    text
    的值,则需要显式强制转换!类似:
    选择聚合有效性(国家变量作为文本类型::regclass,1)参见:还考虑附加模块<代码> RangeEAGG。我在上面添加了指针。我已经在这个阶段确保了间隙和重叠,因此这不需要考虑-但感谢提醒。
    
    select * from aggregate_validity(country, 1)
    =>
    select * from aggregate_validity('country', 1);
    
    CREATE OR REPLACE AGGREGATE range_merge(anyrange) (
       SFUNC = range_merge
     , STYPE = anyrange
    );
    
    -- DROP FUNCTION IF EXISTS aggregate_validity(entity_name regclass, entry bigint);
    CREATE OR REPLACE FUNCTION aggregate_validity(entity_name regclass, entry bigint, OUT result tsrange)
      LANGUAGE plpgsql AS
    $func$
    BEGIN
       EXECUTE 'SELECT range_merge(valid) FROM ' || entity_name || ' WHERE entity_id = $1'
       INTO result
       USING entry;
    END
    $func$;
    
    SELECT aggregate_validity('country', 1);