简体   繁体   中英

SQL - complicate JOIN query

In a tutorial I saw this SQL query:

SELECT a.id as a_id, a.info as a_info, 
       b.id as b_id, b.info as b_info 
FROM stats AS a 
JOIN stats as b
ON a.id != b.id 
LIMIT 25

The query is working well, but now I would need to add the WHERE condition. I have the table users . The table stats contains the column user_id . I try to obtain all users from the table stats if users.city=1 (for example), but I still cannot to find a way, how to achieve that...

My problem is, that I currently have no clue, how to put into the query another JOIN (for table users ).

I would be grateful for every advice, thank you

So this is what you've got...

This is what you return

SELECT a.id as a_id, a.info as a_info, b.id as b_id, b.info as b_info 

This is where it comes from

FROM stats AS a 
JOIN stats as b on a.id != b.id 

This is how many you want

LIMIT 25

So if you want to add the users table, add this after the other joins

JOIN users ON a.user_id = users.id

and to filter it, add this after the joins

WHERE users.city=1

Giving

SELECT a.id as a_id, a.info as a_info, b.id as b_id, b.info as b_info 
FROM stats AS a 
JOIN stats as b on a.id != b.id 
JOIN users ON a.user_id = users.id
WHERE users.city=1
LIMIT 25

For convenience, I've reformatted your original SQL statement to make it readable by humans.

SELECT a.id   AS a_id
     , a.info AS a_info
     , b.id   AS b_id
     , b.info AS b_info
  FROM stats a
  JOIN stats b
    ON a.id != b.id 
 LIMIT 25

Your current query is almost returning a Cartesian product. Every row from stats is getting matched with every row from stats, except for matching itself. (Assuming that stats.id is a primary key or unique key.)

To add a join to the users table, to limit rows returned from a , for example:

SELECT a.id   AS a_id
     , a.info AS a_info
     , b.id   AS b_id
     , b.info AS b_info
  FROM stats a
  JOIN users au ON au.id = a.user_id AND au.city=1
  JOIN stats b ON a.id != b.id 
 LIMIT 25

If you want to limit rows returned for both a and b , add another join to the users table:

SELECT a.id   AS a_id
     , a.info AS a_info
     , b.id   AS b_id
     , b.info AS b_info
  FROM stats a
  JOIN users au ON au.id = a.user_id AND au.city=1
  JOIN stats b ON a.id != b.id 
  JOIN users bu ON bu.id = b.user_id AND bu.city=1
 LIMIT 25

This is not the only way to accomplish this. For example, you could use an a.user_id IN (subquery) or an EXISTS (subquery) predicate.

(SQL is much easier to work with if you have it formatted in a way that is readable.)

Here is one way to do that:

SELECT a.id as a_id, a.info as a_info, 
       b.id as b_id, b.info as b_info 
FROM stats AS a 
JOIN stats as b
     ON a.id != b.id 
where a.user_id in (select user_id from users where users.city = 1)
LIMIT 25

You can also express this as a join (which in MySQL is more efficient):

SELECT a.id as a_id, a.info as a_info, 
       b.id as b_id, b.info as b_info 
FROM stats AS a 
JOIN stats AS b
     ON a.id != b.id 
JOIN users AS u
     ON a.user_id = u.user_id 
     AND u.city_id = 1
LIMIT 25

Well, as you use the table stats two times in your query, you would actually need two joins for the users table as well. (for stats A and stats B)

SELECT a.id as a_id, a.info as a_info, 
       b.id as b_id, b.info as b_info 
FROM stats AS a 
JOIN stats AS b ON a.id != b.id 
JOIN users AS a_users ON a.user_id = a_users.id
JOIN users AS b_users ON b.user_id = b_users.id
WHERE a_users.city = 1 
   OR b_users.city = 1
LIMIT 25

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM