2017-04-20 75 views
0

我一直在使用相同的SQL查詢幾個小時,它終於工作。但是,這是非常緩慢..我一直在試圖優化它,但沒有運氣,任何幫助。下面是該查詢(批號的左連接...):股票與緩慢的SQL查詢

$sql ="SELECT u.id, u.display_name, IFNULL(SUM(r.total_rating)/COUNT(r.total_rating), 0) AS avg_rating, s.title AS study FROM users u 
    LEFT JOIN rating r ON u.id = r.user_id 
    LEFT JOIN usermeta m ON u.id = m.user_id 
    LEFT JOIN usermeta m1 ON u.id = m1.user_id 
    LEFT JOIN studies s ON m.meta_value = s.id 
    WHERE m.meta_key = 'study' AND m1.meta_key = 'subjects' AND m1.meta_value REGEXP '$subjectsvalues' 
    GROUP BY u.id, r.total_rating 
    ORDER BY avg_rating DESC 
    LIMIT 10"; 

表結構,用戶表:

id | display_name | email 
------------------------- 
1 | Khar   | ... 
2 | SantaCruz | ... 

表結構的評價表:

id | rating_title | total_rating | user_id 
------------------------------------------- 
1 | dffd   | 5    | 1 
2 | fddfdffdd | 4    | 1 

的表結構usermeta表格:

id | user_id | meta_key | meta_value 
------------------------------------- 
1 | 1  | study  | 132 
2 | 1  | subjects | 121,231 

爲研究表表結構:

id | title 
---------- 
1 | dsdsf 
2 | sdfdf 

主題值,像這樣的處理:

$subjectsvalues = ''; 

$subjects = explode(",", $subjects); 
foreach($subjects as $val) { 
    $subjectsvalues = $subjectsvalues.",".$val.",|"; 
} 
$subjectsvalues = $subjectsvalues."notdata"; 
+0

這是很多左連接。請編輯您的問題以包含表格的表格結構以及您的預期結果。 –

+0

嗨@JenR,我已更新帖子,謝謝! –

+0

你確定查詢結果是否正確?您正在按'r.total_rating'進行分組,並在同一列上計算「SUM」和「COUNT」agreggates。我認爲這個分組應該放在'u.id,u.display_name,s.title' – Xint0

回答

0

首先,left join s爲不必要的。所以,試試這個:

SELECT u.id, u.display_name, AVG(r.total_rating) AS avg_rating, s.title AS study 
FROM users u JOIN 
    rating r 
    ON u.id = r.user_id JOIN 
    usermeta m 
    ON u.id = m.user_id JOIN 
    usermeta m1 
    ON u.id = m1.user_id JOIN 
    studies s 
    ON m.meta_value = s.id 
WHERE m.meta_key = 'study' AND m1.meta_key = 'subjects' AND m1.meta_value REGEXP '$subjectsvalues' 
GROUP BY u.id, r.total_rating 
ORDER BY avg_rating DESC 
LIMIT 10; 

然後,我會傾向於嘗試usermeta(meta_key, user_id, meta_value)指標。我假設表中的主要ID都是主鍵。

+0

好的,我明白了。我會給它一個鏡頭,謝謝一堆!順便說一句,我已更新帖子,以包括表結構。 –

+0

嗨戈登,我已更新帖子,包括表結構和$ subjectvalues變量。我將如何去索引? –

0

我不能建議編輯Gordon Linoff的答案,所以這是一個改進版本。你不需要joinusermeta兩次,除非usermeta正在與自己比較。

SELECT u.id, u.display_name, AVG(r.total_rating) AS avg_rating, s.title AS study 
FROM users u JOIN 
    rating r 
    ON u.id = r.user_id JOIN 
    usermeta m 
    ON u.id = m.user_id JOIN 
    studies s 
    ON m.meta_value = s.id 
WHERE m.meta_key = 'study' OR (m.meta_key = 'subjects' AND m.meta_value REGEXP '$subjectsvalues') 
GROUP BY u.id, r.total_rating 
ORDER BY avg_rating DESC 
LIMIT 10; 

另外,你能解釋一下你的正則表達式的效用嗎?它很可能不會與$任何內容匹配,表明該模式的結束位於正則表達式的開始位置。

+0

感謝您的回答!非常有幫助,$ subjectvalues是一個包含我們正在搜索的主題ID的變量。例如。 ,142213。 –

+0

您應該爲問題添加[tag:PHP]標籤。 –

+0

我已經添加了一個php標記,謝謝! –