2016-03-07 57 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