在 RETURNS TABLE pgplsql 函数中添加字段

Add field in RETURNS TABLE pgplsql function

如何在 plpgpsql 函数的 RETURNS TABLE 中添加字段,我要添加的值在函数内部执行的 SELECT 中不存在:

我有这个函数可以在 start_date 和 end_date 之间每隔 'step' 秒对作业使用的 cpu 和 ram 的总和进行采样(纪元时间戳):

CREATE OR REPLACE FUNCTION resources(start_date INTEGER, end_date INTEGER, step INTEGER) 
RETURNS TABLE (
    cpu bigint
  , ram bigint)  AS $$
DECLARE
   counter INTEGER := 0 ;
BEGIN
  counter := start_date;
  LOOP 
    EXIT WHEN counter > end_date ;
RETURN QUERY EXECUTE
    'SELECT sum(j_ram) as ram, sum(j_cpu) as cpu from jobs where j_start_time <= ' || counter || ' and j_end_time >= ' || counter;
    counter := counter + step ; 
  END LOOP ; 

END;
$$ LANGUAGE plpgsql;    

输出结果类似于:

 cpu   |  ram 
-------+------
     0 |      
     6 | 12000
     6 | 11000
     1 | 1000

如何在 table 中添加变量 'counter' 的值以得到类似于 :

 cpu   |  ram  | counter 
-------+-------+--------
     0 |       |     100        
     6 | 12000 |     110      
     6 | 11000 |     120       
     1 |  1000 |     130      

这里不需要动态SQL。如果你忽略它,你可以简单地将变量添加到 select:

CREATE OR REPLACE FUNCTION resources(start_date INTEGER, end_date INTEGER, step INTEGER) 
  RETURNS TABLE (
      cpu bigint
    , ram bigint 
    , counter bigint)  
AS $$

DECLARE
   counter INTEGER := 0;
BEGIN
  counter := start_date;
  LOOP 
    EXIT WHEN counter > end_date;

    RETURN QUERY 
      SELECT sum(j_ram) as ram, sum(j_cpu) as cpu, counter 
      from jobs 
      where j_start_time <= counter 
        and j_end_time >= counter;

    counter := counter + step; 
  END LOOP; 

END;
$$ LANGUAGE plpgsql;   

您的情况实际上不需要 EXECUTE,因为没有表名、列名等动态参数。只有传递给 where 子句的值会发生变化。计数器可以是 select.

的一部分
CREATE OR REPLACE FUNCTION resources(start_date INTEGER, end_date INTEGER, 
step INTEGER) 
RETURNS TABLE (
    cpu bigint
  , ram bigint
  , counter int)  AS $$
DECLARE
   counter INTEGER := 0 ;
BEGIN
  counter := start_date;
  LOOP 
    EXIT WHEN counter > end_date ;
RETURN QUERY 
    SELECT sum(j_ram)::bigint as ram, sum(j_cpu)::bigint as cpu,
           counter from jobs 
        where j_start_time <= counter
    and  j_end_time >= counter;
    counter := counter + step ; 
  END LOOP ; 
END;
$$ LANGUAGE plpgsql;    

我建议您避免循环,使用 generate_series 的单个查询会很好 enough.The 函数然后可以是一个简单的 SQL 函数 除非你有其他事情要做 return 只是一个查询结果。

CREATE OR REPLACE FUNCTION resources2(start_date INTEGER, end_date INTEGER, 
step INTEGER) 
RETURNS TABLE (
    cpu bigint
  , ram bigint
  , counter int)  AS $$
   SELECT sum(j_ram) :: BIGINT AS ram, 
         sum(j_cpu) :: BIGINT AS cpu, 
       g.counter 
    FROM   jobs j 
       JOIN (SELECT generate_series(start_date, end_date, step) AS counter) g 
         ON j_start_time <= g.counter 
            AND j_end_time >= g.counter 
   GROUP  BY g.counter 
    ORDER  BY g.counter; 
$$ LANGUAGE sql;   

Demo