简体   繁体   中英

Selecting records where all joined rows match

Given the following schema:

employees
id | name

employee_attributes
id | employee_id | key | value

I would like to select all employees that have the provided attributes.

The following statement works:

SELECT employees.* FROM employees
INNER JOIN employee_attributes ON employee_attributes.employee_id = employees.id
WHERE employee_attributes.key = 'foo' AND employee_attributes.value = 'bar'

but only allows me to find an employee by one attribute. How can I adapt this to retrieve employees by more than one attribute?

To be clear, if I supply two sets of attributes to match against, the query should only return employees that have at least those two attributes .

For example, if Bob has just one attribute:

key | value
===========
foo | bar

But I supply two attributes to the query ( foo and bar , bin and baz ), Bob should not be returned.

Use conditional aggregation:

SELECT employees.*
FROM employees
INNER JOIN employee_attributes
    ON employee_attributes.employee_id = employees.id
GROUP BY employee_attributes.employee_id
HAVING SUM(CASE WHEN employee_attributes.key = 'foo' AND
                     employee_attributes.value = 'bar' THEN 1 ELSE 0 END) > 0 AND
       SUM(CASE WHEN employee_attributes.key = 'bin' AND
                     employee_attributes.value = 'baz' THEN 1 ELSE 0 END) > 0

Following should work:

SELECT employees.id, employees.name, count(employee_attributes.id) as attribute_count FROM employees
INNER JOIN employee_attributes ON employee_attributes.employee_id = employees.id
WHERE (employee_attributes.key = 'foo' AND employee_attributes.value = 'bar') OR (employee_attributes.key = 'bin' AND employee_attributes.value = 'baz')
group by employees.id, employees.name
having attribute_count >= 2;

You can get the employee ids using aggregation:

SELECT ea.employee_id
FROM employee_attributes.employee_id 
WHERE (ea.key = 'foo' AND ea.value = 'bar') OR
      (ea.key = 'bin' AND ea.value = 'baz')
GROUP BY ea.employee_id
HAVING COUNT(DISTINCT ea.key) = 2;

For the full information, you can use a JOIN :

SELECT e.*
FROM employee e JOIN
     (SELECT ea.employee_id
      FROM employee_attributes.employee_id 
      WHERE (ea.key = 'foo' AND ea.value = 'bar') OR
            (ea.key = 'bin' AND ea.value = 'baz')
      GROUP BY ea.employee_id
      HAVING COUNT(DISTINCT ea.key) = 2
     ) ea
     ON ea.employee_id = e.id;

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