MySQL считает все записи, которые имеют хотя бы одну запись в сводной таблице

#mysql

#mysql

Вопрос:

Я пытаюсь посмотреть, имеет ли запись таблицы хотя бы одну запись в сводной таблице, которая используется в отношениях «многие ко многим».

Обслуживающий персонал таблицы:

 | ID |  NAME  |
|----|--------|
| 1  | Name A |
| 2  | Name B |
| 3  | Name C |
 

И сводная таблица Attendant_Event имеет следующую структуру

 | ID |  attendant_id  |  event_id  |  uuid  |
|----|----------------|------------|--------|
| 1  |       1        |      1     |   xxx  |
| 2  |       1        |      2     |   yyy  |
| 3  |       3        |      1     |   zzz  |
| 4  |       3        |      2     |   www  |
| 5  |       1        |      3     |   xyx  |
| 6  |       3        |      3     |   rer  |
 

Мой запрос пытается подсчитать обслуживающий персонал, у которого есть хотя бы одна запись в сводной таблице, но считать все записи как одну.
Например, ожидаемым результатом будет таблица, подобная этой:

 | STATUS |  COUNT |
|--------|--------|
|   YES  |    2   | 
|   NO   |    1   |
 

Эти результаты ожидаемы, потому что:

  1. Только участники с идентификаторами 1 и 3 имеют запись в таблице Attendant_Event. Это говорит нам о том, что количество обслуживающих лиц со строками в сводной таблице равно 2.
  2. У обслуживающего персонала с идентификатором 2 нет записей, поэтому число обслуживающих сотрудников, у которых нет записей в сводной таблице, равно 1.

На данный момент мой запрос следующий:

SELECT IF(uuid <=> NULL, 'NO', 'YES') as status, count(*) as count FROM attendants att LEFT JOIN attendant_event ae ON ae.attendant_id = att.id GROUP BY status

Но это показывает мне такой результат.

 | STATUS |  COUNT |
|--------|--------|
|   YES  |    6   | 
|   NO   |    1   |
 

Это означает, что подсчитайте каждую из строк. Если мы возьмем предыдущий пример, оба участника с идентификаторами 1 и 3 имеют по 3 записи в сводной таблице. Таким образом, он дает 6 вместо двух, которые я ищу.

Что я делаю не так?

Ответ №1:

Возможно, вы захотите сначала выбрать идентификаторы сопровождающих с их соответствующими ДА / НЕТ, а затем посчитать их, что-то вроде:

 SELECT status, count(distinct attendant_id) as count FROM (
   SELECT IF(ae.uuid IS NULL, 'NO', 'YES') as status, ae.attendant_id
   FROM attendants att LEFT JOIN attendant_event ae ON ae.attendant_id = att.id
   GROUP BY ae.attendant_id) x
GROUP BY status
 

Комментарии:

1. Спасибо, это сработало, но я должен перевести запрос в конструктор запросов Laravel. Это было то, что я думал сделать, но я не знал как. Спасибо

Ответ №2:

Когда вы выполняете левое соединение, вы создаете пересечение, которое больше, чем таблица участников. Ваше соединение состоит из строк с повторяющимися attendant_id и разными событиями uuid .

Вы можете наблюдать за пересечением , выполнив SELECT IF(uuid <=> NULL, 'NO', 'YES') as status, att.id, ae.uuid FROM attendants att LEFT JOIN attendant_event ae ON ae.attendant_id = att.id команду . Он включает в себя 7 строк, 6 из них с событиями «ДА» для двух активных участников и 1 строка без событий.

Таким образом, вы должны считать только отдельные значения:

 SELECT IF(uuid <=> NULL, 'NO', 'YES') as status, count(distinct(att.id)) as count 
   FROM attendants att 
   LEFT JOIN attendant_event ae ON ae.attendant_id = att.id 
   GROUP BY status