2011-03-08 70 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部分。

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