Использование условной агрегации:
SELECT t1.id, t1.name
FROM users t1
INNER JOIN
(
SELECT s.user_id
FROM skills s
GROUP BY s.user_id
HAVING SUM(CASE WHEN s.skill LIKE '%php%' OR
s.skill LIKE '%mysql%' THEN 1 ELSE 0 END) >= 2
) t2
ON t2.user_id = t1.id
внутренний запрос находит пользователей, которые имеют как PHP
и MySQL
мастерство, и этот результат затем используется для фильтрации users
таблицы возвращать только имена, которые соответствуют этому требованию.
В моем запросе предполагается, что данный навык появится один раз и только один раз для данного пользователя. Если один и тот же навык может появиться несколько раз для одного и того же пользователя, запрос нужно будет слегка изменить.
Update:
Если skills
таблица может иметь один и тот же навык, указанный для данного пользователя несколько раз, вы можете игнорировать эти повторяющиеся записи, используя DISTINCT
:
SELECT t1.id, t1.name
FROM users t1
INNER JOIN
(
SELECT s.user_id
FROM (SELECT DISTINCT user_id, skill FROM skills) s
GROUP BY s.user_id
HAVING SUM(CASE WHEN s.skill LIKE '%php%' OR s.skill LIKE '%mysql%'
OR s.skill LIKE '%javascript%' THEN 1 ELSE 0 END) >= 3
) t2
ON t2.user_id = t1.id
Обратите внимание, что в «Скрипке» ниже отметка «Марк» не отображаются в результирующем наборе, как Хотя у него PHP как навык, перечисленный дважды, у него нет ни MySQL, ни JavaScript.
Он никогда и ничего не возвращают. Пожалуйста, посмотрите здесь, я просто сделал SQL-схему http://sqlfiddle.com/#!9/5008a6/1 – Ridd
@Ridd Я думаю, вы хотите использовать оператор 'OR', а не' AND'. Проверьте мое обновление. –
Это работает, отлично! Спасибо. Это сложнее, но я надеюсь, что это тоже эффективно и не убьет мой db :) Еще раз спасибо. – Ridd