MySQL where joined value is multiple ANDs

d-_-b :

Running into a seemingly simple JOIN problems here..

I have two tables, users and courses

| users.id | users.name |
| 1        | Joe        |
| 2        | Mary       |
| 3        | Mark       |
| courses.id | courses.name |
| 1          | History      |
| 2          | Math         |
| 3          | Science      |
| 4          | English      |

and another table that joins the two:

| users_id | courses_id |
| 1        | 1          |
| 1        | 2          |
| 1        | 3          |
| 2        | 1          |

I'm trying to find distinct user names who are in course 1 and course 2

It's possible a user is in other courses, too, but I only care that they're in 1 and 2 at a minimum

SELECT DISTINCT(users.name)
FROM users_courses
LEFT JOIN users ON users_courses.users_id = users.id
LEFT JOIN courses ON users_courses.courses_id = courses.id
WHERE courses.name = "History" AND courses.name = "Math"
AND courses.name NOT IN ("English")

I understand why this is returning an empty set (since no single joined row has History and Math - it only has one value per row.

How can I structure the query so that it returns "Joe" because he is in both courses?

Update - I'm hoping to avoid hard-coding the expected total count of courses for a given user, since they might be in other courses my search does not care about.

forpas :

Join users to a query that returns the user ids that are in both courses:

select u.name
from users u 
inner join (
  select users_id
  from users_courses
  where courses_id in (1, 2)
  group by users_id
  having count(distinct courses_id) = 2
) c on c.users_id = u.id

You can omit distinct from the condition:

count(distinct courses_id) = 2

if there are no duplicates in users_courses.
See the demo.

If you want to search by course names and not ids:

select u.name
from users u 
inner join (
  select uc.users_id
  from users_courses uc inner join courses c
  on c.id = uc.courses_id
  where c.name in ('History', 'Math')
  group by uc.users_id
  having count(distinct c.id) = 2
) c on c.users_id = u.id

See the demo.
Results:

| name |
| ---- |
| Joe  |

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=5599&siteId=1