[thelist] mysql join and subqueries

Phil Turmel philip at turmel.org
Fri Jun 3 22:51:07 CDT 2005


partyarmy wrote:
> having trouble with a complicated (for me) sql statement.
> 
> SELECT members.member_id 
> FROM members 
> LEFT JOIN profile 
> ON members.member_id=profile.member_id 
> WHERE members.city = 'vancouver' AND profile.category_id = '0' AND
> profile.profile_data LIKE '%three%'
> LIMIT 0, 20
> 
> so far this works great, but, i need to take the result set, which
> will be a bunch of member_id's and do this query.
> 
> SELECT COUNT(member_id) FROM logins WHERE member_id = ???????;
> 
> where the ??????? are the member_id's from the JOIN above. then, order
> by the total number of logins.
> 
> not sure if this can be done without using subqueries for my server is
> still reluctant to upgrade.
> 
> any help will be greatly appreciated. thanks guys.
> 
> codi lechasseur
Hi codi,

Simplification opportunity first:

Your first query might not need a JOIN at all... Are all `member_id`s in 
profile also in members (or supposed to be)?  If so, your first query 
simplifies to:

SELECT member_id
   FROM profile
   WHERE city = 'vancouver' AND category_id = '0' AND
     profile_data LIKE '%three%'
   LIMIT 0, 20

If `member_id`s could be in profile but not members, and you really want 
to exclude them, at least change the LEFT JOIN to INNER JOIN.  With 
conditions on city, category, and profile_data from profiles, any 
records from members that have no matching profile data will get tossed 
anyways.  Might as well do it in the JOIN, which should be much faster.

Now for the count you're looking for:

If you have the luxury of subquery support, I recommend this:

SELECT member_id, count(*) AS logincount
   FROM logins
   WHERE member_id IN (SELECT member_id
     FROM profile
     WHERE city = 'vancouver' AND category_id = '0' AND
       profile_data LIKE '%three%'
     LIMIT 0, 20)
   GROUP BY member_id
   ORDER BY logincount DESC

I'm presuming you want to know who's logging in the most, so I put the 
DESC qualifier on the ORDER clause.

I'm not sure the LIMIT clause is really where you want it, though.  You 
may want to allow all matching member profiles, count 'em up, sort 
descending, then cut it off at twenty results.  Like so:

SELECT member_id, count(*) AS logincount
   FROM logins
   WHERE member_id IN (SELECT member_id
     FROM profile
     WHERE city = 'vancouver' AND category_id = '0' AND
       profile_data LIKE '%three%')
   GROUP BY member_id
   ORDER BY logincount DESC
   LIMIT 0, 20

But you might not be able to use subqueries, so convert to a JOIN instead:

SELECT logins.member_id, count(*) AS logincount
   FROM logins INNER JOIN profile
     ON logins.member_id = profile.member_id
   WHERE city = 'vancouver' AND category_id = '0' AND
     profile_data LIKE '%three%'
   GROUP BY logins.member_id
   ORDER BY logincount DESC
   LIMIT 0, 20


HTH,

Phil


More information about the thelist mailing list