2012-03-20 59 views
1

我想將計數(*)查詢的結果分組爲值桶。我在dellstore2 postgresql示例數據庫上測試了這一點。我的查詢下面返回正確的答案,但爲表中的每一行做了一次(幾千個相同的結果)。我可以通過在查詢結尾添加LIMIT 1來解決這個問題,但是我想知道爲什麼我會收到重複項,以防指向更廣泛的問題。查詢是:爲什麼count(*)在此子查詢(postgresql)中返回多個結果?

SELECT 
    (SELECT count(*) 
     FROM 
      orders 
     WHERE 
      totalamount > 0 AND totalamount <= 100) AS ">0 <= 100", 
    (SELECT count(*) 
     FROM 
      orders 
     WHERE 
      totalamount > 100 AND totalamount <= 200) AS ">100 <= 200" 
... 
FROM 
    orders; 

編輯 Andomar的回答也讓我發現下面的方法(改編自SQL簡而言之(O'Reilly)的一個例子)。這讓我可以在一列中放置桶,併爲每個桶/答案配對一排。我想我會將它包含在任何具有該用例的人中:

SELECT CASE 
     WHEN totalamount IS NULL THEN 'Unknown' 
     WHEN totalamount <= 100 THEN 'Not more than 100' 
     WHEN totalamount <= 200 THEN 'Not more than 200' 
     ELSE 'Over 200' 
    END "Bucket", 
    COUNT(*) "Number of results" 
FROM 
    orders 
GROUP BY CASE 
     WHEN totalamount IS NULL THEN 'Unknown' 
     WHEN totalamount <= 100 THEN 'Not more than 100' 
     WHEN totalamount <= 200 THEN 'Not more than 200' 
     ELSE 'Over 200' 
    END 
ORDER BY 
    MIN(totalamount); 
+0

似乎有幾個圓括號缺失。請發佈真實的代碼。 – wildplasser 2012-03-20 12:11:12

+0

感謝wildplasser - 現在修復了(我正在處理兩臺未連接的機器,因此無法剪切和粘貼)。 – 2012-03-20 12:18:08

回答

6

您正在從orders中選擇每一行,然後對每一行評估子查詢。

考慮使用此方法代替:

select count(case when 0 < totalamount and totalamount <= 100 then 1 end) 
      as "<0,100]" 
,  count(case when 100 < totalamount and totalamount <= 200 then 1 end) 
      as "<100,200]" 
from Orders 

這將在一個單一的表掃描計算都聚集。

+0

謝謝Andomar,那很完美。 – 2012-03-20 12:28:18

3

因爲您將它們作爲子查詢包含在內。從它的外觀來看,對於orders表中的每一行都執行count子查詢。如果您從主查詢中省略from部分,則只應獲得一行。

例如,查詢

SELECT 'John Doe' FROM orders 

返回「李四」在訂單表的每一行。

SELECT 'John Doe' 

僅選擇一個行。

聲明:這是sql server的行爲。

+0

謝謝傑西,這工作,但我已勾選上述Andomar的解決方案,因爲我覺得他對查詢的方法比我的原始更可讀。 – 2012-03-20 12:29:46

相關問題