我可以让 postgres plpgsql 函数返回可变列记录吗?

2023-12-05

我想创建一个 postgres 函数来构建它的列集 即时返回;简而言之,它应该接受一个键列表,构建 每个键一列,并返回由该集组成的记录 列数是。简而言之,代码如下:

CREATE OR REPLACE FUNCTION reports.get_activities_for_report() RETURNS int[] AS $F$
BEGIN
    RETURN ARRAY(SELECT activity_id FROM public.activity WHERE activity_id NOT IN (1, 2));
END;
$F$
LANGUAGE plpgsql
STABLE;

CREATE OR REPLACE FUNCTION reports.get_amount_of_time_query(format TEXT, _activity_id INTEGER) RETURNS TEXT AS $F$
DECLARE
    _label TEXT;
BEGIN
    SELECT label INTO _label FROM public.activity WHERE activity_id = _activity_id;
    IF _label IS NOT NULL THEN
        IF lower(format) = 'percentage' THEN
            RETURN $$TO_CHAR(100.0 *$$ ||
            $$ (SUM(CASE WHEN activity_id = $$ || _activity_id || $$ THEN EXTRACT(EPOCH FROM ended - started) END) /$$ ||
            $$ SUM(EXTRACT(EPOCH FROM ended - started))),$$ ||
            $$ '990.99 %') AS $$ || quote_ident(_label);
        ELSE
            RETURN $$SUM(CASE WHEN activity_id = $$ || _activity_id || $$ THEN ended - started END)$$ ||
            $$ AS $$ || quote_ident(_label);
        END IF;
    END IF;
END;
$F$
LANGUAGE plpgsql
STABLE;

CREATE OR REPLACE FUNCTION reports.build_activity_query(format TEXT, activities int[]) RETURNS TEXT AS $F$
DECLARE
    _activity_id INT;
    query TEXT;
    _activity_count INT;
BEGIN
    _activity_count := array_upper(activities, 1);
    query := $$SELECT agent_id, portal_user_id, SUM(ended - started) AS total$$;
    FOR i IN 1.._activity_count LOOP
        _activity_id := activities[i];

        query := query || ', ' || reports.get_amount_of_time_query(format, _activity_id);
    END LOOP;
    query := query || $$ FROM public.activity_log_final$$ ||
    $$ LEFT JOIN agent USING (agent_id)$$ ||
    $$ WHERE started::DATE BETWEEN actual_start_date AND actual_end_date$$ ||
    $$ GROUP BY agent_id, portal_user_id$$ ||
    $$ ORDER BY agent_id$$;
    RETURN query;
END;
$F$
LANGUAGE plpgsql
STABLE;

CREATE OR REPLACE FUNCTION reports.get_agent_activity_breakdown(format TEXT, start_date DATE, end_date DATE) RETURNS SETOF RECORD AS $F$
DECLARE
    actual_end_date DATE;
    actual_start_date DATE;
    query TEXT;
    _rec RECORD;
BEGIN
    actual_start_date := COALESCE(start_date, '1970-01-01'::DATE);
    actual_end_date := COALESCE(end_date, now()::DATE);
    query := reports.build_activity_query(format, reports.get_activities_for_report());

    FOR _rec IN EXECUTE query LOOP
        RETURN NEXT _rec;
    END LOOP;
END
$F$
LANGUAGE plpgsql;

这构建的查询(大致)如下所示:

SELECT agent_id, 
    portal_user_id, 
    SUM(ended - started) AS total, 
    SUM(CASE WHEN activity_id = 3 THEN ended - started END) AS "Label 1"
    SUM(CASE WHEN activity_id = 4 THEN ended - started END) AS "Label 2"
FROM public.activity_log_final 
    LEFT JOIN agent USING (agent_id) 
WHERE started::DATE BETWEEN actual_start_date AND actual_end_date 
GROUP BY agent_id, portal_user_id 
ORDER BY agent_id

当我尝试拨打电话时get_agent_activity_breakdown()函数,我收到此错误:

psql:2009-10-22_agent_activity_report_test.sql:179: ERROR:  a column definition list is required for functions returning "record"
CONTEXT:  SQL statement "SELECT * FROM reports.get_agent_activity_breakdown('percentage', NULL, NULL)"
PL/pgSQL function "test_agent_activity" line 92 at SQL statement

当然,诀窍在于标有“标签 1”和“标签”的列 2' 取决于内容中定义的活动集 活动表,我在调用函数时无法预测。如何 我可以创建一个函数来访问这些信息吗?


如果您确实想动态创建这样的表,也许只需在函数中创建一个临时表,这样它就可以包含您想要的任何列。让函数将所有行插入表中而不是返回它们。该函数可以仅返回表的名称,或者您可以只返回一个您知道的确切表名称。运行该函数后,您只需从表中选择数据即可。该函数还应该检查临时表是否存在,以便删除或截断它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以让 postgres plpgsql 函数返回可变列记录吗? 的相关文章

随机推荐

  • 在一台计算机上打开工作簿错误代码 32809,但在另一台计算机上打不开

    我有一个 Excel 2013 宏工作簿 本工作簿在过去 6 个月中一直运行良好 今年的第一天 我遇到了下面的问题 代码如下 这行代码所做的就是在打开工作簿时将 activex 复选框控件设置为 true Sheets WSCHARTS c
  • 将字符串分成两部分,长度几乎相同

    我有字符串 这是一个示例字符串 我需要将其拆分为 2 个字符串 而不破坏单词 并且这两个字符串将具有最接近的长度 因此结果将是 This is a sample string 另一个例子 Gorge is nice gt Gorge is
  • Rails /lib 模块和

    我正在编写一个自定义包装器open flash chart插入 它被放置在 lib并将其作为模块加载ApplicationController 但是 我有类层次结构的问题或其他问题 从我可以访问的任何控制器open flash chart功
  • 如何使用 VBA 验证 SAP GUI 中的活动窗口

    我目前正在尝试使用 VBA 修复 SAP 过程中的一些问题 现在我有一段代码可以正确处理有时出现的错误弹出窗口 If session findById wnd 2 usr txtMESSTXT1 Text Material j atuali
  • 有什么充分的理由使用 FormCollection 而不是 ViewModel 吗?

    我继承了用 ASP Net MVC 4 编写的代码库 每个 post 方法都需要一个FormCollection 除了必须通过带引号的字符串访问值的烦恼之外 它还会导致一些缺点 例如无法使用诸如ModelState IsValid or A
  • 如何在c中确定linux中的目录或文件

    我只想打印文件名而不打印目录名称 所以我实现了这个功能 void list file char directory DIR d struct dirent dir d opendir directory if d while dir rea
  • clientHeight/clientWidth 在不同浏览器上返回不同的值

    特性document body clientHeight and document body clientWidth在 IE7 IE8 和 Firefox 上返回不同的值 IE 8 document body clientHeight 70
  • Elasticsearch 结合多个存储桶和聚合

    假设我们正在查看相当简单的数据 索引中的每个文档都具有以下结构 Time 2018 01 01T19 35 00 0000000Z Country Germany Addr security web com FailureCount 5 S
  • 在 R 中生成一个具有 m 列和 n 行的随机矩阵,其中行总和为 1

    我想生成一个 nxm 矩阵 假设它是 100x3 我希望每一行的总和为 1 因此两个 0 和一个 1 sample c 0 0 1 3 会给我 1 行 但是有没有一种非常快速的方法可以在没有 rbind 的情况下生成整个矩阵 谢谢你 没有循
  • 如果值不存在,则将数组对象推入另一个数组对象

    如果值不存在 需要将数组对象 arr1 的值推送到另一个数组对象 arr2 中 现有值不会推入另一个数组 var arr1 name fred name bill name ted name james var arr2 name spil
  • Android,当我在设备上安装应用程序时图标重复

    我尝试在我的设备上安装我开发的应用程序 Htcdesire 我发现该应用程序的图标是重复的 我需要改变什么才不会迟到发生这种情况 我怎样才能删除其中一个图标 感谢您的帮助 我今天遇到这个问题 我正在使用 Gradle 我发现有一个文件夹 b
  • Android,在 onClickListener 中使用 Toast

    我试图让 toast 在 onClickListener 内给定某些条件时显示一些文本 该应用程序无法在模拟器中运行 并且出现以下错误 void 无法转换为 Toast 我四处搜索 在这个论坛上找到了几个类似的问题和解决方案 但没有一个完全
  • Python 的 Requests 库中的 Session 对象线程安全吗?

    Python 的流行Requests该库在其主页上据说是线程安全的 但没有给出更多细节 如果我打电话requests session 然后我可以安全地将这个对象传递给多个线程 如下所示 session requests session fo
  • Java中模块的动态加载

    在 Java 中 我可以动态地将内容添加到类路径并加载类 动态 意味着无需重新启动我的应用程序 是否有一个已知的框架 库可以处理模块的动态加载 卸载而无需重新启动 通常的设置 尤其是 Web 应用程序 是负载均衡器 多个应用程序实例以及逐步
  • 填充控制台中的最后一行

    我想填充 更新控制台的整个底线 例子 static void Main string args Console BufferWidth Console WindowWidth Console BufferHeight Console Win
  • 恒定 FPS Android OpenGLES

    你好安卓开发者 我正在 Eclipse 中使用 OpenGLES 1 0 为 Android 开发一个简单的游戏 我使用 Samsung Galaxy S2 Android 2 3 作为开发设备 我有一个关于双核和使帧速率恒定的问题 因此
  • 在javascript中重置文本区域高度

    我有一个文本区域 自动调整大小 我想清除其所有内容 包括其高度 到目前为止我已经尝试过 document getElementById textarea value And document getElementById textarea
  • 如何在pandas中将一列分成三列

    我有一个数据框 如下所示 ID Name Address 1 Kohli Country India State Delhi Sector SE25 2 Sachin Country India State Mumbai Sector SE
  • 可以在触发器内动态创建 JOB 吗?

    该触发器的执行失败 它编译但一旦我执行指定的插入 gt 错误 create or replace TRIGGER AFT INSERT TMP TBL AFTER INSERT ON TMP TBL REFERENCING OLD AS O
  • 我可以让 postgres plpgsql 函数返回可变列记录吗?

    我想创建一个 postgres 函数来构建它的列集 即时返回 简而言之 它应该接受一个键列表 构建 每个键一列 并返回由该集组成的记录 列数是 简而言之 代码如下 CREATE OR REPLACE FUNCTION reports get