将 PostgreSQL 函数包装在另一个中以有条件地组合结果

Posted

技术标签:

【中文标题】将 PostgreSQL 函数包装在另一个中以有条件地组合结果【英文标题】:Wrap PostgreSQL functions in another to conditionally combine results 【发布时间】:2019-09-23 01:48:58 【问题描述】:

我有一个函数get_oversight(int),它返回一列:

person_id
----------
100
101
102
103
104

还有另一个函数get_unfiltered_responsibility(int) 返回相同的结构:

person_id
----------
100
103
104

我需要一个评估并返回上述子集的第三个函数。这是一些伪代码:

def function get_responsibility(person_id int):
    oversight = get_oversight(person_id)
    unfiltered_responsibility = get_responsibility(person_id)

    if number_of_records(unfiltered_responsibility) == 0:
        return oversight
    else
        return intersection(unfiltered_responsibility, oversight)
        # only ids from unfiltered_responsibility that are ALSO IN oversight

第三个函数会是什么样子? (使用 v9.6)

【问题讨论】:

那个代码不是 PL/pgSQL 我将其描述为伪代码......只是想描述我正在寻找的逻辑。 【参考方案1】:

假设两个函数都不会返回重复项。否则,您必须准确定义如何处理这些问题。

plpgsql函数中,您可以方便地使用特殊变量FOUND

CREATE OR REPLACE FUNCTION get_combo_plpgsql(int)
  RETURNS TABLE(person_id int) LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY
   SELECT *
   FROM   get_oversight($1)
   JOIN   get_unfiltered_responsibility($1) USING (person_id);

   IF NOT FOUND THEN
      RETURN QUERY
      SELECT * FROM get_oversight($1);
   END IF;
END
$func$;

假设get_unfiltered_responsibility() 始终返回get_oversight() 的子集,就像您的示例数据似乎暗示的那样。然后,如果连接没有返回任何行,我们可以断定get_unfiltered_responsibility() 出现空。

相关:

Why is IS NOT NULL false when checking a row type?

或者,这个 CTE 包装在一个简单的 SQL 函数 中,无论是否是子集(如果需要,也可以是 plpgsql 函数),在任何情况下都可以工作:

CREATE OR REPLACE FUNCTION get_combo_sql(int)
  RETURNS TABLE(person_id int) LANGUAGE sql AS
$func$
WITH cte AS (SELECT * FROM get_unfiltered_responsibility($1))
SELECT *
FROM   get_oversight($1) o
WHERE  EXISTS (
   SELECT FROM cte
   WHERE  person_id = o.person_id
   )
OR NOT EXISTS (TABLE cte)
$func$;

相关:

Is there a shortcut for SELECT * FROM?

db小提琴here

【讨论】:

以上是关于将 PostgreSQL 函数包装在另一个中以有条件地组合结果的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql 在另一个函数中调用一个函数,从主函数传递一个参数

将查询结果存储在变量中以在 Postgresql 中的另一个查询中使用

是否可以将代码包装在一个块中以在调用一个变量时执行整个块?

如何将我在 EditText 框中键入的数据添加到数组中以在另一个活动中列出?

Swift 使用完成处理程序将视图锁定在一个控制器中以反映在另一个控制器中

WPF:如何将内容控件包装在另一个中?