2012-02-29 157 views
1

基本上,我想要做的是將某個出生年份內的所有子項都放在另一個表中。所以我有兩張桌子。比方說,這是一個校表Mysql在主要查詢中使用子查詢的結果

學校

school_id 
child_id 

兒童

child_id 
birth_year 
name 
etc 

我第一次嘗試是使用子查詢,這是這樣的

SELECT *, (SELECT COUNT(*) FROM school LEFT JOIN children ON school.child_id = children.child_id) as total FROM school LEFT JOIN children ON school.child_id = children.child_id GROUP BY birth_year 

這個查詢的問題是子查詢將在整個記錄中運行,所以如果我有1000條記錄,我認爲查詢(和子查詢)將在由birth_year分組之前運行1000次,這很慢,差不多是3-5秒爲500個樣本數據。

所以要優化它,我正在這樣做。

遞歸查詢使用PHP

首先,讓所有的孩子誰在學校的不同出生年份。所以我要查詢像

SELECT birth_year FROM school LEFT JOIN children ON school.child_id = children.child_id 

它會返回像

birth_year 
========== 
2009 
2010 
2011 

我敢在PHP另一個查詢要使用的數據(比方說我,結果存儲到$ row變量)

foreach ($row as $r){ 
    $new_array[] = count($this->db->get_child_data($r->birth_year)); //this is pseudocode only, to get the number of children data who have birth_year of 2009-2011 
} 

雖然它會運行額外的三個查詢,但由於計數非常簡單,因此速度非常快。 500個樣本數據只需要不到0.5秒的時間。

但是,我想知道是否有任何方法來優化它?或者更好的是,有沒有辦法在具有相似性能的單個查詢中執行?

我試圖做到這一點,但它最終超慢,崩潰了我的WAMP。

SELECT * FROM children WHERE birth_year IN (SELECT GROUP_CONCAT(DISTINCT birth_year) FROM school LEFT JOIN children ON school.child_id = children.child_id) 

子查詢

SELECT GROUP_CONCAT(DISTINCT birth_year) FROM school LEFT JOIN children ON school.child_id = children.child_id 

當單獨運行正常,並迅速返回

2009,2010,2011 

當我查詢

SELECT * FROM children WHERE birth_year IN (2009,2010,2011) 

它也快,所以我相當困惑爲什麼當我加入這兩個查詢s,我的WAMP崩潰的速度很慢。

對不起提前

回答

2

問題的長期職位和感謝的是,使用在INSELECT條款子查詢往往使他們在外部查詢的每一行被再次運行。爲了避免這種情況,請嘗試加入子查詢。這應該導致子查詢只運行一次,並被緩存。

SELECT c.* 
FROM children c, (SELECT birth_year FROM school LEFT JOIN children ON school.child_id = children.child_id GROUP BY birth_year) b 
WHERE c.birth_year = b.birth_year 

這就是說,它看起來像你剛剛在任何一所學校得到每個孩子無論如何,所以一個簡單的JOIN也可以給你同樣的結果。

SELECT c.* 
FROM children c, school s 
WHERE c.child_id = s.child_id 

如果你只是想獲得孩子的數量在每所學校,每個birth_year

SELECT count(c.child_id), s.* 
FROM school s 
LEFT JOIN children c ON c.child_id = s.child_id 
GROUP BY s.school_id, c.birth_year 
+0

實際上我試過用s ubquery,看到我的第一次嘗試,因爲我想每年都得到孩子的總數。瓶頸似乎像計數子查詢雖然... – Henson 2012-02-29 05:25:51

+0

這裏的關鍵是子查詢的位置。但我必須說,你的最終目標是什麼並不完全清楚。 – Umbrella 2012-02-29 05:37:18

+0

我想我會用遞歸PHP查詢,它的速度很快,我說的是4秒(子查詢)與0.2秒(遞歸PHP)。你是對的,我的最終目標是每年都要讓所有的孩子上學,最簡單的方法就是遞歸查詢,因爲它讓PHP能夠完成艱苦的工作 – Henson 2012-02-29 05:44:15

-1

如果你試圖讓一個出生年份兒童人數

SELECT COUNT (c.child_id) FROM child c INNER JOIN school s ON (c.child_id = s.child_id) GROUP BY birthyear 

如果你需要額外的過濾器,那麼你可以添加一個你想要的年的where子句

+0

這就是我在第一次嘗試時所要做的:SELECT *,(SELECT COUNT(*)FROM school LEFT JOIN children ON school.child_id = children.child_id)作爲總共FROM學校LEFT JOIN children on school.child_id = children.child_id GROUP BY birth_year這很慢。我認爲在子查詢中加入學校與兒童是必要的,以提供更準確的結果(因此不包括未在學校的兒童) – Henson 2012-02-29 05:29:15