2015-06-15 67 views
1

裏面一個大的查詢主叫COUNT兩次,我必須COUNT變量,然後如果它大於1,具有計數作爲字符串否則空字符串:避免在CASE表達式(PostgreSQL的)

CASE COUNT(measurement.id) > 1 THEN to_char(COUNT(measurement.id),' 999') ELSE '' 

恐怕這很慢,因爲我使用COUNT()兩次。有沒有更好的辦法?

+1

計數只會被評估一次。 –

+0

那會很棒,是在文檔的某處? – RemcoGerlich

+1

@RemcoGerlich。 。 。波動性的定義非常強烈(http://www.postgresql.org/docs/9.4/static/xfunc-volatility.html)。我認爲這適用於聚合函數,並且'COUNT()'被正確聲明爲穩定。 –

回答

3

這個表達式:因爲COUNT()被稱爲兩次

CASE COUNT(measurement.id) > 1 THEN to_char(COUNT(measurement.id),' 999') ELSE '' 

不慢。彙總數據的艱鉅工作是將關鍵值集中在一起的部分。單獨的聚合功能通常不是特別昂貴(有例外,如COUNT(DISTINCT))。所以,即使它被多次調用,這也不是問題。

你可以查詢更改爲更具神祕狀:

coalesce(to_char(nullif(count(measurement.id), 0), '999')), '') 

這需要的計數爲0,將其轉換爲NULL,然後將其變成一個空字符串(我認爲它會只在Postgres中評估一次參數,儘管SQL Server會評估它兩次,在這種情況下,您使用isnull()而不是coalesce())。我更喜歡你的版本,如果你覺得有必要把漂亮的數字轉換成字符串。

編輯:

COUNT()似乎被定義爲「不可變的」,這是比「穩定的」甚至更強。我甚至不確定這是否正確,但SQL Fiddle就是這種情況。無論如何,它可能不會被調用兩次,但昂貴的部分無論如何都是GROUP BY

+0

(對於這篇小論文,我有點不高興了......)聚合實際上並沒有一個公開的穩定課。 'pg_proc'中的條目只是一個佔位符,用來保留函數簽名,並防止在非聚合上下文中調用(注意'prosrc'只是['aggregate_dummy'](https://github.com/postgres) /postgres/blob/aa9eac45ea868e6ddabc4eb076d18be10ce84c6a/src/backend/executor/nodeAgg.c#L2888),所以'IMMUTABLE'可能適合)。 –

+0

穩定性類的整體概念不能(很容易)在這裏應用,因爲明顯的行爲(將一個集映射到標量值的函數)與現實非常不同(驅動一系列狀態轉換的一系列值) 。大多數轉換函數在技術上都是'VOLATILE',儘管它們有聲明,因爲它們在累加器上執行就地更新。 'COUNT()'函數有點違背分類,因爲它實際上修改了它的輸入...... –

+0

除此之外,聚合的行爲就像'STABLE'一樣(即使它們不是):[SQLFiddle](http ://www.sqlfiddle.com/#!15/70ef4/1) –