2014-02-28 91 views
1

我想執行多個共享相同WHERE子句的SQL查詢。我的查詢都涉及統計各組中的條目數量。目前,我正在分別執行每個查詢,這可能導致WHERE過濾器被多次應用。這看起來很浪費。有沒有什麼辦法可以將我的查詢結合在一起,使WHERE子句只被調用一次?更一般地說,有什麼辦法可以讓查詢更高效嗎?如何使用相同的WHERE子句高效地執行多個SQL查詢

具體來說,假設我有一張公衆人物表。

PublicFigures

last_name | occupation | age | state | has_dogs 
--------------------------------------------------- 
Stewart | comedian  | 51 | NY | true 
Colbert | comedian  | 49 | NJ | false 
Obama  | president | 52 | DC | true 
Romney | consultant | 66 | CA | true 
(etc..) 

我想從表中提取兩種類型的信息。首先,我想知道每個職業每個姓氏的出現頻率,其次,我希望每個州都有關於狗所有權的數據。在這兩種情況下,我只對55歲以下的公衆人物感興趣。因此,這兩個查詢都使用相同的WHERE條款。

的第一個查詢,姓名和職業,看起來像這樣

SELECT last_name, occupation, COUNT(*) as count WHERE age < 55 FROM "PublicFigures" GROUP BY last_name, occupation 

,並給出了這個

last_name | occupation | count 
--------------------------------- 
Stewart | comedian  | 1 
Stewart | president | 0 
Colbert | comedian  | 1 
Colbert | president | 0 
Obama  | comedian  | 0 
Obama  | president | 1 

第二個查詢是這樣的:

SELECT state, has_dogs, COUNT(*) as count WHERE age < 55 FROM "PublicFigures" GROUP BY state, has_dogs 


state | has_dogs | count 
--------------------------------------------------- 
NY | true  | 1 
NY | false | 0 
NJ | true  | 0 
NJ | false | 0 
DC | true  | 1 
DC | false | 1 

是否有辦法得到這些結果比分別用這兩個查詢更有效率?這兩個查詢可以以某種方式組合嗎?

在現實生活中,當然,我的表更大,我有更多的查詢,而且我的過濾條件更復雜。我認爲從聰明的SQL中可以節省的成本是相當可觀的。如果可能,我特別喜歡Rails3友好的ActiveRecord中的解決方案。

任何想法?

+0

有兩個相對簡單的查詢比一個非常複雜的查詢更好。 –

+0

呵呵。好。這可能是事實。不是我期待的答案,但你可能是對的!謝謝。 –

+0

另一種方法是通過窗口函數進行計數,即通過(由...分區)而不是分組,但我同意Sam D在可能時避免非常複雜的查詢。 – Jayvee

回答

1

這是索引將創造奇蹟的地方。另一種可與索引創建結合的方法是一次篩選多次。希望這會給你買東西,但正確的索引可能是你需要的。

CREATE INDEX pidx_public_figures_age ON public_figures (age) 
WHERE age < 55; 
--Try temp table with the index and also try just the new index and see if all your queries now run as fast as you would hope. 
CREATE TEMPORARY TABLE temp_public_figures AS 
SELECT last_name, occupation ,age, state, has_dogs 
FROM films WHERE age < 55; 

現在運行查詢,無論是對實際的表或臨時表的方法你N多,看看如果你可以讓每個查詢更快的執行下你的使用情況

SELECT last_name, occupation, COUNT(*) as count 
FROM temp_public_figures 
GROUP BY last_name, occupation; 

SELECT state, has_dogs, COUNT(*) as count 
FROM temp_public_figures 
GROUP BY state, has_dogs; 
+0

在他們創造奇蹟的正確數據分佈下特別注意該部分索引。 http://www.postgresql.org/docs/9。3 /靜態/索引-partial.html – Kuberchaun

2

更好例如,創建索引是一個獨立的基礎,這將是您最好的選擇。如果沒有,然後創建一個臨時表,然後重複查詢它而不是原來的:

create temporary table young_figures as 
    select * from public_figures where age < 55;