Оптимизация запросов MySQL устраняет ненужные объединения - PullRequest
0 голосов
/ 09 марта 2011

Концептуально, я пытаюсь получить 8 отдельных результатов опроса для каждого пользователя в моей системе. Я хочу вывести все 8 баллов, связанных с данным пользователем, выведенных в той же строке. Вот мой лучший способ добиться этого:

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

Это возвращает правильный вывод, но, однако, очень медленно. Как бы вы посоветовали мне его оптимизировать?

Ответы [ 2 ]

3 голосов
/ 09 марта 2011

Первое, что вам нужно, это индекс для 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 голосов
/ 09 марта 2011

Вы можете немного настроить это дальше:

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 часть.

Кроме того, ответ Ричарда - вещь красоты.

...