georgich
@georgich

Как выбрать записи из таблицы, одновременно имеющие несколько значений?

Приветствую!
Делаю фильтр для сайта. Приведу пример структуры базы.
1. Таблица employee
5dad6d6e32f73903536599.jpeg
2. Таблица services
5dad6d8f93b80186121316.jpeg
3. Таблица empl_services
5dad6da66d655658017983.jpeg
Необходимо сделать запрос на выборку людей, у которых присутствуют выбранные пользователем услуги. Т.е. если на сайте указываем галочками "Крутит гайки" и "Гнёт арматуру", то ни одной записи не будет найдено. А вот если укажем "Крутит гайки" и "Носит ящики", то нашлись бы две записи - Петя и Коля.
Простой запрос, аля
SELECT employee_id FROM empl_services WHERE services_id = 1 AND services_id = 3

по понятным причинам работать не будет. Подскажите, пожалуйста, как решить данную задачу? Спасибо.
  • Вопрос задан
  • 207 просмотров
Решения вопроса 2
erge
@erge
Примус починяю
как-то так:

см. на sqlfiddle
select e.id, e.name
  from employee e
  join (
    select employee_id
      from empl_services es
      join services s on s.id = es.service_id
      where s.title in ('Крутит гайки','Носит ящики')
      group by employee_id
      having count(1) = 2
  ) t on t.employee_id = e.id
;

-- если id услуг известны то так:

select e.id, e.name
  from employee e
  join (
    select employee_id
      from empl_services es
      where service_id in (1,3)
      group by employee_id
      having count(1) = 2
  ) t on t.employee_id = e.id
;


PS: тут обязательно надо в выражении having count(1) = ?? подставлять количество услуг перечисляемых в IN(...)
на 8ке можно по другому через WITH, а в having count(1) подставлять count по подзапросу услуг...

UPD:
на 8ке так:

with 
s as (
  select id from services where title in ('Крутит гайки','Носит ящики')
),
r as (
  select employee_id from empl_services es
    join s on s.id = es.service_id
    group by employee_id
    having count(employee_id) = (select count(1) from s)
)
select *
  from employee e
  join r on r.employee_id = e.id
;


см. на dbfiddle
Ответ написан
irishmann
@irishmann
Научись пользоваться дебаггером
Создал три таблицы

5dad89798d3b9274522896.jpeg
5dad8980a2caf693545505.jpeg
5dad8986644cf567980782.jpeg


Кто крутит гайки и носит ящики? (1 и 3 services_id)

Нужны люди и их услуги
Запрос

SELECT
	e.`id` as `employee_id`,
	e.`name` as `employee_name`,
    s.`id` as `service_id`,
    s.`title` as `service_title`
FROM
	`empl_services` es 
    LEFT JOIN `employee` e ON es.`employee_id` = e.`id`
    LEFT JOIN `services` s ON es.`services_id` = s.`id`
WHERE
	s.`id` in(1, 3)


Результат

5dad89c90b0a3861396613.jpeg

Нам нужны только люди, убираем лишнее
Запрос

SELECT
	e.`id`,
	e.`name`
FROM
	`empl_services` es 
    LEFT JOIN `employee` e ON es.`employee_id` = e.`id`
WHERE
	es.`services_id` in(1, 3)
GROUP BY e.`id`


Результат

5dad8c8026483981998554.jpeg

Нужны только идентификаторы, убираем лишнее
Запрос

SELECT
	es.`employee_id`
FROM
	`empl_services` es 
WHERE
	es.`services_id` in(1, 3)
GROUP BY es.`employee_id`


Результат

5dad8d4c724f9938209483.jpeg


UPD. Нужны employee у которых есть обe services_id
Запрос

SELECT
	es.`employee_id`,
    e.`name`
FROM
	`empl_services` es
    LEFT JOIN `employee` e ON es.`employee_id` = e.`id`
WHERE
	es.`services_id` in (1, 3)
GROUP BY es.`employee_id`
HAVING (COUNT(*) = 2)


Результат

5dad937a4a2df400196441.jpeg
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
inoise
@inoise
Solution Architect, AWS Certified, Serverless
Select t.*, Count(t.id) z from (select ..... Union select ....) As t Group by t.id having z = 2
Ответ написан
tsklab
@tsklab
Здесь отвечаю на вопросы.
Это уже было. В вашем случае нужно соединять псевдонимы по employee_id.
Ответ написан
LaRN
@LaRN
Senior Developer
Можно так попробовать:
select en.Name
  from empl_services es
 inner join services ss
         on ss.id     = es.services_id
        and ss.title in ('Крутит гайки', 'Гнёт арматуру')
 inner join employee em
         on ss.id     = es.employee_id
 group by en.Name
having count(1) = 2
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы