Reputation: 700
I want to do a complex SELECT between more tables (4+) that will order and count items.
So far this is what my line is :
SELECT
myl_u.id,
myl_u.label_real_address,
myl_u.ext,
COUNT(myc_c.contact_id),
COUNT(myl_r_c.release_id)
FROM
myl_users myl_u
LEFT JOIN myc_contacts myc_c ON myc_c.contact_type='l' AND myc_c.contact_id=myl_u.id
LEFT JOIN myl_releases myl_r ON myl_r.id=myl_u.id
LEFT JOIN myl_r_comments myl_r_c ON myl_r.release_id=myl_r_c.release_id
GROUP BY myl_u.label_real_address
ORDER BY COUNT(myc_c.contact_id) DESC
It's half working, but when I add the latter part of the SQL, it shows unexpected values and it doubles them too somehow.
Basically I have myl_users (a collection of record labels) myc_contacts (how many favourites does a user have, contact_type='l' means it's about myl_users and not other table) myl_releases contains music releases (like EP, album, with unique id's and myl_r_comments contains comments regular users do to these releases.
I managed to ORDER by how many favourites a record label has (15, 14, 10, 8..) - the COUNT(myc_c.contact_id) clause
but when I add the next clause and make the query bigger to order by the total comments the releases from labels have, unexpected appears.
Can someone pinpoint me to the right way ?
I will comment and adapt / clarify the question by your needs.
thanks, have a happy new year
Upvotes: 1
Views: 95
Reputation: 1270391
The problem is that you are summing along multiple dimensions, so you are getting a cross product. The best way is to summarize along each dimension independently:
SELECT myl_u.id, myl_u.label_real_address, myl_u.ext,
sum(myc_c.cnt),
sum(myl_rc.cnt)
FROM myl_users myl_u LEFT JOIN
(select contact_id, count(*) as cnt
from myc_contacts myc_c
where myc_c.contact_type='l'
group by contact_id
) myc_c
ON myc_c.contact_id=myl_u.id LEFT JOIN
(select myl_r.id, count(*) as cnt
from myl_releases myl_r LEFT JOIN
myl_r_comments myl_r_c
ON myl_r.release_id=myl_r_c.release_id
gropu by myl_r.id
) myl_rc
ON myl_rc.id=myl_u.id
GROUP BY myl_u.id, myl_u.label_real_address, myl_u.ext
ORDER BY 4 DESC
It is not clear from the question whether the final group by
is necessary. If there are no duplicates in the myl_u table, then you don't need the outside aggregation at all.
Upvotes: 1
Reputation: 103145
At least one problem that I spot is that you need a WHERE clause if you want to restrict the rows. The JOINs should only include the considtions of the JOINs.
SELECT
myl_u.id,
myl_u.label_real_address,
myl_u.ext,
COUNT(myc_c.contact_id),
COUNT(myl_r_c.release_id)
FROM
myl_users myl_u
LEFT JOIN myc_contacts myc_c ON myc_c.contact_id=myl_u.id
LEFT JOIN myl_releases myl_r ON myl_r.id=myl_u.id
LEFT JOIN myl_r_comments myl_r_c ON myl_r.release_id=myl_r_c.release_id
WHERE
myc_c.contact_types = '1'
GROUP BY myl_u.label_real_address
ORDER BY COUNT(myc_c.contact_id) DESC
Also, are you sure its a left join that you want? That returns all rows from the "left" table even if no matching values on the right. Try changing LEFT to INNER and see if you get what you are expecting.
Upvotes: 0