2017-04-20 13 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 

テーブル構造ユーザテーブル:

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

クエリの結果はOKですか?あなたは 'r.total_rating'でグループ化し、' SUM'を計算し、 'COUNT'は同じ列で一致させます。グループ化は '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

さて、わかった。私はそれをショットを与えるだろう、おかげで束! Btw、私はテーブルの構造を含めるために投稿を更新しました。 –

+0

こんにちはGordon、私はテーブルの構造と$ subjectvalues変数を含むように投稿を更新しました。どのようにインデックスを作成するのですか? –

0

Gordon Linoffの答えを編集することはできませんので、ここでは改善されたバージョンです。 usermetaをそれ自身と比較しない限り、joinにはusermetaを2回使用する必要はありません。

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

あなたの答えをありがとう!非常に参考になります、$ subjectsvaluesは、私たちが探している件名を含む変数です。例えば。 、142,213。 –

+0

[tag:PHP]タグを質問に追加する必要があります。 –

+0

私はPHPタグを追加しました、ありがとう! –