Извлечение строк, содержащих несколько записей ассоциации

Вопрос:

Предположим, что у меня есть таблица типа ASOC со следующими данными:

+----------+----------+
| PERSON   | SKILL    |
+----------+----------+
| Bob      | Java     |
| Bob      | Database |
| Sarah    | Java     |
| Sarah    | HTML     |
| Jane     | Java     |
| Jane     | HTML     |
| Jane     | Database |
+----------+----------+

Я хочу запрос, который вернет список людей, обладающих навыками Java и базы данных, то есть Боба и Джейн.

Если я запустил запрос, например:

SELECT PERSON
FROM   PERSON_SKILLS_ASOC
WHERE  SKILL = 'Java'
OR     SKILL = 'Database'

Я тоже получу Сару, которая не претендует на позицию, которую я пытаюсь заполнить. Нужно ли мне делать какой-то запрос на объединение/пересечение?

Я нахожусь в MySQL. Заранее спасибо.

Лучший ответ:
select a.person
from (select person from person_skills_asoc where skill = 'Java') a
     (select person from person_skills_asoc where skill = 'Database') b
where a.person = b.person;

или

select a.person
from person_skills_asoc a, person_skills_asoc b
where a.person = b.person
  and a.skill = 'Java'
  and b.skill = 'Database';

Ответ №1

Я не работал в MySQL много лет, поэтому мой синтаксис может быть немного, но суть EXISTS:

SELECT
PSA1.Person
FROM
PERSON_SKILLS_ASOC AS PSA1
WHERE
PSA1.Skill = 'Java'
AND EXISTS (SELECT * FROM PERSON_SKILLS_ASOC AS PSA2 WHERE PSA1.Person = PSA2.Person AND PSA2.Skill = 'Database')

Вы также можете добиться этого с помощью соединения.

Ответ №2

В SQL Server, например, вы можете использовать INTERSECT, по-видимому, недоступный в MySQL (еще?). Возможное решение, использующее самосоединение (проверьте SQLFiddle):

SELECT P1.PERSON
FROM   PERSON_SKILLS_ASOC AS P1
INNER JOIN PERSON_SKILLS_ASOC AS P2 ON P1.PERSON = P2.PERSON
WHERE  P1.SKILL = 'Java'
AND P2.SKILL = 'Database';

Также есть еще один приятный ответ на SO по альтернативам для INTERSECT в MySQL: qaru.site/questions/95269/….

Ответ №3

Использование таких объединений: —

SELECT a.PERSON
FROM   PERSON_SKILLS_ASOC a
INNER JOIN PERSON_SKILLS_ASOC b ON a.PERSON = b.PERSON
WHERE  a.SKILL = 'Java'
AND    b.SKILL = 'Database'

Или используя подсчеты: —

SELECT PERSON
FROM   PERSON_SKILLS_ASOC a
WHERE  SKILL IN ('Java', 'Database')
GROUP BY PERSON
HAVING  COUNT(DISTINCT SKILL) = 2

Оцените статью
TechArks.Ru
Добавить комментарий