【问题标题】:Postgres recursive building of CTE with array values具有数组值的 CTE 的 Postgres 递归构建
【发布时间】:2019-12-10 15:17:44
【问题描述】:

我有一个代表函数名称的字符串数组。我需要遍历它们才能调用每个函数。它们根据与函数中其他表匹配的条件来区分不同的行。我需要单独查询的累积行,并认为递归 CTE 将是可行的方法。但是,我无法增加引用数组索引的数字。有什么建议吗?此外,如果这只是一种不好的方法,那么任何提示都会很棒:D

CREATE OR REPLACE FUNCTION fn_name(target_table TEXT, identifier INT) returns setof table_name as
$$
DECLARE
 function_names text[];
BEGIN
  function_names := '{fn1, fn2, fn3}';
  WITH RECURSIVE non_matches(n) as (
    SELECT * FROM non_matching_records($1, $2, function_names[1])
    UNION
    SELECT * FROM non_match_records($1, $2, function_names[n+1] 
      WHERE n < ARRAY_LENGTH(function_names, 1) + 1
  )
  SELECT * FROM non_matches;
END
$$ LANGUAGE plpgsql;

编辑:删除了对同一个表返回的引用。我忘了这就是为什么我要接受 table 参数所以它可以返回 void。我需要从每个函数返回的记录集合,以便能够对它们运行另一个查询。

更新:

这是我的递归查询 atm 所在的位置:

WITH RECURSIVE non_matches AS (
        SELECT *, 1 AS depth FROM non_matching_records($1, $2, function_names[1])
        UNION
        SELECT c.*, nm.depth + 1 AS depth FROM non_matching_records($1, $2, function_names[nm.depth]) c, non_matches nm
    )
    SELECT * FROM non_matches;

如果我不包含 CTE 名称,我从此更新收到的错误是没有名为 depth 的列。如果我使用它,则没有 CTE 条目。不太确定如何访问括号中的内容以访问数组。

non_matching_records 是一个查找不匹配记录的函数。

【问题讨论】:

  • 您是否尝试过使用窗口函数获取索引?试试这个代码:WITH j AS ( SELECT unnest('{fn1, fn2, fn3}'::TEXT[]) AS f ) SELECT row_number() OVER (ORDER BY 1)-1 AS idx, f FROM j(索引从0开始)
  • 我没有,现在试试 :D
  • 好的。让我知道它是否有帮助......没有你的环境很难测试:)另一个选择是这样的:SELECT row_number() OVER (ORDER BY 1)-1 AS idx, f FROM (SELECT unnest('{fn1, fn2, fn3}'::TEXT[]) AS f) AS j
  • @JimJones 我无法完成这项工作。我想我不确定你是否有实现的愿景:(

标签: postgresql plpgsql


【解决方案1】:

我会遍历数组并使用RETURN QUERY EXECUTE 来调用每个函数。

CREATE OR REPLACE FUNCTION fn_name(target_table regclass, identifier INT) returns setof table_name AS
$$
DECLARE 
  function_names regproc[] := '{fn1, fn2, fn3}';
  fn regproc;
BEGIN
  FOREACH fn IN ARRAY function_names
  LOOP
    RETURN QUERY EXECUTE format('SELECT * FROM %s(%s, %L)', fn, $1, $2);
  END LOOP;
  RETURN;
END;
$$ LANGUAGE PLPGSQL;

我在这里使用了 regclass 和 regproc 来帮助对表和函数进行模式限定,但只要您注意它们的调用方式,您就可以将它们改回文本。

【讨论】:

  • 对不起杰里米,我解决了我的问题。我忘记了为什么我将表名作为参数。因为我需要能够访问找到的所有记录并插入到不同模式中的几个不同表中。根据输入的表名,返回表会有所不同:(对此感到抱歉。但感谢您提供 regclass 和 regproc。我不知道这些。我只想让事情变得更安全 :D
【解决方案2】:

昨晚终于到了。事实证明,一旦我添加了 depth 列,我最初选择的是 from 错误的“表格”。我切换了表的顺序,首先是 cte,然后 then 加入返回记录的函数。这使我可以访问深度列并允许我增加索引

WITH RECURSIVE non_matches AS (
        SELECT c.*, 1 AS depth FROM non_matching_records($1, $2, function_names[1]) c
        UNION
        SELECT c.*, nm.depth + 1 as depth 
        FROM non_matches nm, non_matching_records($1, $2, function_names[nm.depth]) c
        WHERE nm.depth < array_length(match_rules, 1) + 1
    )

【讨论】:

    猜你喜欢
    • 2017-06-28
    • 2022-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    相关资源
    最近更新 更多