Christian
Christian

Reputation: 638

SQL SELECT query with multiple conditions

I'm stuck with a SQL query. Let's say we have an employee, a task table and a many to many association between them. The tables look like this:

employees
id|name
1 | John
2 | Peter
3 | Mike

tasks
id | name
1 | Support
2 | Programming
3 | Call customers
4 | Write Newsletters
5 | Write Invoices

employees_tasks
employee_id | task_id
1 | 1
1 | 2
2 | 3
2 | 4
2 | 5
3 | 2

Now I want to get all employees, who have "Programming" as their tasks. The correct query is:

SELECT employees.id, employees.name
FROM employees 
    INNER JOIN employees_tasks ON employees.id = employees_tasks.employee_id
    INNER JOIN tasks ON employees_tasks.task_id = tasks.id
WHERE
    tasks.name LIKE 'Programming'

So far so good... But now I want to get all employees, whose tasks are "Programming" and "Support". This query gives me NULL:

SELECT employees.id, employees.name
FROM employees 
    INNER JOIN employees_tasks ON employees.id = employees_tasks.employee_id
    INNER JOIN tasks ON employees_tasks.task_id = tasks.id
WHERE
    tasks.name LIKE 'Programming' AND tasks.name LIKE 'Support'

I receive three records with this query

SELECT employees.id, employees.name
FROM employees 
    INNER JOIN employees_tasks ON employees.id = employees_tasks.employee_id
    INNER JOIN tasks ON employees_tasks.task_id = tasks.id
WHERE
    tasks.name IN ('Programming', 'Support')

2x John and 1x Mike. But that's not what I want. I want all employees, who have the tasks "Programming" AND "Support" - not those, who only have one of the tasks.

There's another option. I use ALL with a subquery. Here we go:

SELECT employees.id, employees.name
FROM employees 
    INNER JOIN employees_tasks ON employees.id = employees_tasks.employee_id
    INNER JOIN tasks ON employees_tasks.task_id = tasks.id
WHERE
    tasks.name = ALL
    (SELECT DISTINCT name
    FROM tasks
    WHERE name LIKE 'Programming' OR name LIKE 'Support')

But I receive with this query NULL, although there is an employee, who have both tasks: John!

How can I implement such a query?

Best Regards Christian

Upvotes: 4

Views: 20837

Answers (1)

eggyal
eggyal

Reputation: 125835

You need to join employees_tasks to your query a second time:

SELECT employees.id, employees.name
FROM employees
  INNER JOIN employees_tasks AS et1 ON employees.id = et1.employee_id
  INNER JOIN employees_tasks AS et2 ON employees.id = et2.employee_id
  INNER JOIN tasks AS t1 ON et1.task_id = t1.id AND t1.name = 'Programming'
  INNER JOIN tasks AS t2 ON et2.task_id = t2.id AND t2.name = 'Support'

UPDATE

Alternatively, if you filter your results for only the tasks of interest, you can GROUP BY employee and only return those who have the desired task count:

SELECT   employees.id, employees.name
FROM     employees
  INNER JOIN employees_tasks ON employees_tasks.employee_id = employees.id
  INNER JOIN tasks           ON employees_tasks.task_id     = tasks.id
WHERE    tasks.name IN ('Programming', 'Support')
GROUP BY employees.id, employees.name
HAVING   COUNT(DISTINCT tasks.id) = 2

Upvotes: 7

Related Questions