2016-03-07 89 views
2

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

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) 

我想从我的函数这一结果。但我得到的错误:

query has no destination for result data

这是我的函数:

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是不对的,但我不知道如何得到这个工作?

回答

1

@Travis已经规定,你需要RETURN QUERY实际上从plpgsql function返回查询结果。

但是,您并不需要plpgsql作为简单的SELECT。改为使用plain SQL function。您需要定义还提供了像@Travis返回类型无论哪种方式,最好使用RETURNS TABLE,但实际上返回的数据类型必须精确匹配:

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。如果你定义返回列requestcounterint,你要投: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') 
+0

Thx为您提供帮助! requestcounter --------------------(“00-01 sec”,2979)(“01-04 sec”,2)这是我的结果 - 有可能它看起来像这样:Kategorien | requestcounter ------------ + ---------------- 00-01 sec | 2073 01-04 sec | 2?最好的问候 这样我有2列? – liquid

+0

@cartmanownz:用'SELECT * FROM ...'调用你的函数来分解行。 –

+0

非常感谢你!我用postgres 9.3.8来试试这个 - 它有效,但是8.4有一个问题。你知道为什么吗? – liquid

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'; 

我觉得你写的功能正在运行无处选择查询发送输出,那么它返回一个空的整数集。 (这就是为什么你得到这个错误。)

+0

谢谢特拉维斯! – liquid