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
Basically live_submissions and num_comments variable display proper results, while the total_points and month_points display a product of month_points/total_points, live_submissions and num_comments. Any idea why this is happening?
This is called a Cartesian Product. When you join the tables together, the default result is every permutation of rows for which the join conditions are true. You use
JOINconditions to limit these permutations.But since you are joining multiple tables to
users, the result includes every permutation of each matching table. For example, each matching row inpointsis repeated per matching row incomments, and each of these is multiplied again, repeating per matching row inrants.You can partially compensate for this with
COUNT(DISTINCT c_id)as you are doing, but theDISTINCTis necessary only because you have multiple rows perc_id. And it doesn’t work unless you apply it to unique values. This remedy doesn’t work for theSUM()expressions.Basically, you’re trying to do too many calculations in one query. You need to split it up into separate queries for it to be reliable. And then you can get rid of the
DISTINCTmodifiers, too.You shouldn’t try to do all three of these in a single query.