在RETURNS TABLE pgplsql函数中添加字段

时间:2019-02-28 09:23:04

标签: postgresql plpgsql

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

我有此功能,可以在开始日期和结束日期(纪元时间戳)之间的每“步”秒内采样作业使用的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

如何在表中添加变量'counter'的值,使其类似于:

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

2 个答案:

答案 0 :(得分:1)

这里不需要动态SQL。而且,如果您忽略了这一点,则只需将变量添加到选择中即可:

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;   

答案 1 :(得分:1)

您实际上不需要EXECUTE,因为没有动态参数,例如表名,列名等。只有传递给where子句的值会发生变化。计数器可以是选择的一部分。

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进行单个查询就足够了。该函数可以是一个简单的 SQL函数,除非您需要执行其他操作而不返回只是查询结果。

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