2011-03-08 21 views
0

從概念上講,我試圖爲系統中的每個用戶獲取8個單獨的調查分數。我想輸出連接到同一行輸出的給定用戶的所有8個分數。這是我的最佳實現:MySQL查詢優化消除不必要的連接

SELECT cp.CONSUMER_ID, 
     bsr1.SCORE AS SET_1_SCORE, 
     bsr2.SCORE AS SET_2_SCORE, 
     bsr3.SCORE AS SET_3_SCORE, 
     bsr4.SCORE AS SET_4_SCORE, 
     bsr5.SCORE AS SET_5_SCORE, 
     bsr6.SCORE AS SET_6_SCORE, 
     bsr7.SCORE AS SET_7_SCORE, 
     bsr8.SCORE AS SET_8_SCORE 
FROM 
CONSUMER_PROFILE AS cp 
LEFT JOIN survey_scores AS bsr1 
ON bsr1.SET_ORDER=1 
AND bsr1.CUSTOMER_ID=cp.CONSUMER_ID 
LEFT JOIN survey_scores AS bsr2 
ON bsr2.SET_ORDER=2 
AND bsr2.CUSTOMER_ID=cp.CONSUMER_ID 
LEFT JOIN survey_scores AS bsr3 
ON bsr3.SET_ORDER=3 
AND bsr3.CUSTOMER_ID=cp.CONSUMER_ID 
LEFT JOIN survey_scores AS bsr4 
ON bsr4.SET_ORDER=4 
AND bsr4.CUSTOMER_ID=cp.CONSUMER_ID 
LEFT JOIN survey_scores AS bsr5 
ON bsr5.SET_ORDER=5 
AND bsr5.CUSTOMER_ID=cp.CONSUMER_ID 
LEFT JOIN survey_scores AS bsr6 
ON bsr6.SET_ORDER=6 
AND bsr6.CUSTOMER_ID=cp.CONSUMER_ID 
LEFT JOIN survey_scores AS bsr7 
ON bsr7.SET_ORDER=7 
AND bsr7.CUSTOMER_ID=cp.CONSUMER_ID 
LEFT JOIN survey_scores AS bsr8 
ON bsr8.SET_ORDER=8 
AND bsr8.CUSTOMER_ID=cp.CONSUMER_ID 

這將返回正確的輸出,但速度非常慢。你會如何建議我優化它?

+0

請發佈'EXPLAIN'輸出。 – derobert 2011-03-08 21:58:47

回答

3

您首先需要的是survey_scores(SET_ORDER,consumer_id,score)或至少survey_scores(SET_ORDER,consumer_id)的索引。即使用你的查詢,它也能很好地工作。

的另一種方式來寫這將是

SELECT cp.CONSUMER_ID, 
     MAX(CASE WHEN bsr1.SET_ORDER=1 THEN bsr1.SCORE END) AS SET_1_SCORE, 
     MAX(CASE WHEN bsr1.SET_ORDER=2 THEN bsr1.SCORE END) AS SET_2_SCORE, 
     MAX(CASE WHEN bsr1.SET_ORDER=3 THEN bsr1.SCORE END) AS SET_3_SCORE, 
     MAX(CASE WHEN bsr1.SET_ORDER=4 THEN bsr1.SCORE END) AS SET_4_SCORE, 
     MAX(CASE WHEN bsr1.SET_ORDER=5 THEN bsr1.SCORE END) AS SET_5_SCORE, 
     MAX(CASE WHEN bsr1.SET_ORDER=6 THEN bsr1.SCORE END) AS SET_6_SCORE, 
     MAX(CASE WHEN bsr1.SET_ORDER=7 THEN bsr1.SCORE END) AS SET_7_SCORE, 
     MAX(CASE WHEN bsr1.SET_ORDER=8 THEN bsr1.SCORE END) AS SET_8_SCORE 
FROM CONSUMER_PROFILE AS cp 
LEFT JOIN survey_scores AS bsr1 
ON bsr1.SET_ORDER in (1,2,3,4,5,6,7,8) 
AND bsr1.CUSTOMER_ID=cp.CONSUMER_ID 
GROUP BY cp.CONSUMER_ID 
0

,可以稍微調整這個進一步:

SELECT ... FROM consumer_profile as cp  
LEFT JOIN survey_scores as bsr1 
ON ((bsr1.Set_Order BETWEEN 1 AND 8) 
    AND (bsr1.Consumer_ID = cp.Consumer_ID)) 
GROUP BY cp.Consumer_ID; 

如果你確信是從未Set_order超出範圍1 .. 8 那麼你可以刪除(bsr1.Set_Order BETWEEN 1 AND 8) AND部分。

其他則理查德的回答是美的事情。