使用SELECT CASE创建函数

时间:2016-03-07 16:31:52

标签: sql postgresql plpgsql return-type set-returning-functions

我想用2个参数创建一个函数。这是我的SELECT声明:

SELECT CASE 
   WHEN duration <=  10000000 THEN '00-01 sec'
           WHEN duration <=  40000000 THEN '01-04 sec' 
           WHEN duration <= 100000000 THEN '04-10 sec' 
           WHEN duration <= 300000000 THEN '10-30 sec' 
           WHEN duration <= 600000000 THEN '30-60 sec' 
           ELSE 'more than 60 sec' END AS "Kategorien", 
   COUNT(*) AS Requestcounter
FROM tablename
WHERE starttime BETWEEN '2016-03-01 00:00:00' AND '2016-03-08 14:00:00'
GROUP BY
  (CASE WHEN duration <=  10000000 THEN '00-01 sec'
   WHEN duration <=  40000000 THEN '01-04 sec' 
   ELSE 'more than 60 sec' END); 

结果:

 Kategorien | requestcounter
------------+----------------
 00-01 sec  |           2073
 01-04 sec  |              2
(2 rows)

我希望这个结果来自我的功能。但是我得到了错误:

  

查询没有结果数据的目的地

这是我的功能:

CREATE OR REPLACE FUNCTION requestcounter(mindate timestamptz,maxdate timestamptz) 
RETURNS SETOF integer AS $$ 

BEGIN
SELECT CASE WHEN duration <=  10000000 THEN '00-01 sec'
            WHEN duration <=  40000000 THEN '01-04 sec'  
            ELSE 'more than 60 sec' END AS "Kategorien", 
COUNT(*) AS Requestcounter from tablename where starttime BETWEEN mindate and maxdate
GROUP BY
  (CASE WHEN duration <=  10000000 THEN '00-01 sec' 
        WHEN duration <=  40000000 THEN '01-04 sec'  
        ELSE 'more than 60 sec' END);
Return; 
END;
$$ LANGUAGE plpgsql;

我知道RETURNS SETOF integer不对,但我不知道如何让它发挥作用?

2 个答案:

答案 0 :(得分:1)

@Travis已经规定您需要RETURN QUERYplpgsql function实际返回查询结果。

但是对于简单的SELECT,您不需要plpgsql。请改用plain SQL function。您需要以任一方式定义返回类型,最好使用RETURNS TABLE,如@Travis也提供,但实际返回的数据类型必须精确匹配:

CREATE OR REPLACE FUNCTION requestcounter(_mindate timestamptz, _maxdate timestamptz) 
  RETURNS TABLE (kategorien text, requestcounter int) AS
$func$ 
SELECT CASE WHEN duration <= 10000000 THEN '00-01 sec'::text
            WHEN duration <= 40000000 THEN '01-04 sec'
            -- more cases ...
            ELSE 'more than 60 sec' END  -- AS kategorien -- not visible outside function
     , count(*)::int                     -- AS requestcounter
FROM   tablename
WHERE  starttime BETWEEN _mindate AND _maxdate
GROUP  BY 1                              -- simpler with positional reference
ORDER  BY 1                              -- see below   
$func$  LANGUAGE sql;                    -- never quote the language name
  • count()返回bigint。如果您将返回的列requestcounter定义为int,则必须强制转换:count(*)::int(或者首先返回bigint。)

  • 在SQL函数中,您可以使用普通SELECT来返回行。

  • 避免参数和列名之间的命名冲突。一个常见的约定是像我一样为参数添加前缀。

  • GROUP BY中的位置参考是SELECT列表中长表达式的非常方便的语法快捷方式。这还可以确保GROUP BY项与SELECT项匹配(在第一次查询中)。

  • 您可能想要添加ORDER BY 1或获得任意订单。您演示的text发生,以正确的顺序排序。

呼叫:

SELECT * FROM requestcounter('2015-01-01 00:00+01', '2015-03-01 00:00+01') 

答案 1 :(得分:0)

我想你要退回一张桌子,而不是SETOF INTEGER

像这样:

CREATE OR REPLACE FUNCTION requestcounter (mindate timestamptz, maxdate timestamptz) RETURNS TABLE (
    Kategorien text,
    requestcounter int
) AS
$BODY$
BEGIN
    RETURN QUERY
    SELECT CASE WHEN duration <=  10000000 THEN '00-01 sec'
                WHEN duration <=  40000000 THEN '01-04 sec'  
                ELSE 'more than 60 sec' END AS "Kategorien", 
    COUNT(*) AS Requestcounter from tablename where starttime BETWEEN mindate and maxdate GROUP BY
    (CASE WHEN duration <=  10000000 THEN '00-01 sec' 
    WHEN duration <=  40000000 THEN '01-04 sec'  
    ELSE 'more than 60 sec' END);
END
$BODY$
LANGUAGE 'plpgsql';

我认为你编写的函数是运行一个无处发送输出的选择查询,然后它返回一组空的整数。 (这就是为什么你会收到这个错误的原因。)