2009-04-02 10 views
2
SELECT user_id, 
    SUM(COALESCE(point_points, 0)) AS total_points, 
    SUM(
     CASE 
      WHEN point_date > '$this_month' 
      THEN point_points 
      ELSE 0 
     END)    AS month_points, 
    COUNT(DISTINCT c_id) AS num_comments, 
    COUNT(DISTINCT rant_id) AS live_submissions 
FROM users 
    LEFT JOIN points 
    ON users.user_id = points.point_userid 
    LEFT JOIN comments 
    ON 
     (
      c_userid = user_id 
     ) 
    LEFT JOIN rants 
    ON 
     (
      rant_poster = user_id 
     AND rant_status = 1 
     ) 
WHERE user_id = $id 
GROUP BY user_id 

基本的live_submissionsnum_comments可変表示正しい結果、total_pointsmonth_pointsmonth_points/total_pointslive_submissionsnum_commentsの製品を表示しています。なぜこれが起こっているのか?なぜこのMySQLクエリの結果が互いに乗算されるのですか?

答えて

9

ような何かをしたいと思います。テーブルを結合すると、デフォルトの結果はのすべての順列の結合条件に該当します。です。これらの置換を制限するには、条件JOINを使用します。

しかし、複数のテーブルをusersに結合するため、結果には一致する各テーブルのすべての置換が含まれます。たとえば、pointsの各一致行は、一致する行につきcommentsで繰り返され、それぞれの行は再び一致し、一致する行はrantsで繰り返されます。

COUNT(DISTINCT c_id)でこれを部​​分的に補うことができますが、c_idごとに複数の行があるため、DISTINCTが必要です。そして、それをユニークな値に適用しなければ機能しません。この対策はSUM()式では機能しません。

基本的に、1つのクエリで多すぎる計算をしようとしています。それを信頼できるものにするためには、別々のクエリに分割する必要があります。そして、DISTINCT修飾子も取り除くことができます。

これらの3つのすべてを1つのクエリで実行しないでください。

+0

良い答えの請求書。 – nickf

0

サンプル出力を提供できますか?

私はそれがポイントで暴言とコメントを追加することと関係があると思います。暴言とコメントの表を削除しようとすることはできますか?

+0

怒りとコメントを削除すると、完全に合算されます。もし私が単純にsum + commentsを持っていれば、それらを2倍にするだけです。私が怒りを加えると、それもまたそれによって乗算されます。 –

-1

グループ化する前にクエリの出力を見ると、問題が表示されます。結合された表に複数のレコードがある場合、ユーザーに対して複数の行が戻されます。したがって、ユーザーが2つのコメント・レコードを持っている場合は、2つのポイント・レコードも戻されます。簡単な例として、

...

ユーザー表

のuserId名

1フレッド

ポイントテーブル

のuserIdポイント

1 10これらのテーブルから

コメントテーブル

のuserIdコメント

ここ

1あり

選択*は

0123コメント

のuserIdポイントになります

1ここ10

1 10あり

私は、MySQLの構文の完全にはよく分からないが、あなたはこれがCartesian Product呼ばれる

SELECT UserId, C.num_comments, P.total_points 
FROM users 
LEFT JOIN 
    (SELECT c_userId, COUNT(DISTINCT c_id) as num_comments 
    FROM Comments 
    GROUP BY c_userId) 
    AS C 
    ON UserId = c_userid 
LEFT JOIN 
    (SELECT point_userId, sum(COALESCE(point_points, 0)) as total_points 
    FROM Points 
    GROUP BY point_userId) 
    AS P 
    ON UserId = point_userid 
+0

グループを削除してもクエリは実行されません。 –

+0

私はあなたが重複している理由を説明しようとしていました。私はMYSQLの構文はわかりませんが、SQL Serverでは、別々のサブクエリからポイント、コメント、票を返すでしょう。 –

関連する問題