如何将天数传递给 Postgres 函数?

1 sql postgresql function plpgsql

days函数中的参数getAvgByDay()不起作用,我猜是因为它在引号内:

CREATE OR REPLACE FUNCTION getAvgByDay(days int)
RETURNS TABLE ( average text,
                date timestamp with time zone
               ) AS
$func$
BEGIN
RETURN QUERY
SELECT to_char( AVG(measure), '99999D22') AS average, ( now() - interval '$1 day') AS date
FROM (
        SELECT mes.date, mes.measure
        FROM measures mes
        WHERE mes.date < ( now() - interval '$1 day')
    ) AS mydata;
END
$func$ 
LANGUAGE plpgsql;

Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 5

假设该列measures.date实际上是数据类型timestamptz而不是date

CREATE OR REPLACE FUNCTION get_avg_by_day(_days int)
  RETURNS TABLE (average text, ts timestamptz) AS  -- not using "date" for a timestamp
$func$
SELECT to_char(avg(measure), '99999D22') -- AS average
     , now() - interval '1 day' * $1     -- AS ts
FROM   measures m
WHERE  m.date < now() - interval '1 day' * $1
$func$  LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
  • 不需要PLpgSQL,可以是更简单的SQL函数。
  • 不需要子查询。只会增加复杂性和成本,却没有任何好处。
  • 外部查询级别不需要列别名。这些未使用,因为可见列名称是在RETURNS子句中定义的。
  • 不需要额外的括号。无论如何,运算符优先级可以按需要工作。(在这种情况下也没有什么坏处。)
  • 如果可以避免的话,不要在 Postgres 中使用 CaMeL 大小写标识符。
  • 不要将timestamptz列称为“日期”。这是误导。使用“ts”代替。
  • 最重要的是:您也有同样的怀疑,并且“粘性位”已经解释过:字符串内没有插值。但只需将时间单位乘以您的integer输入即可减去给定的天数:

    interval '1 day' * $1
    
    Run Code Online (Sandbox Code Playgroud)

    这比字符串连接更快、更干净。