многократный подсчет - PullRequest
       3

многократный подсчет

1 голос
/ 23 августа 2011

У меня есть предметы обучения, комната и учитель.Обучение имеет 0 или несколько комнат.В тренинге участвуют 0 или несколько учителей.

Table training (id,name,town)

Table training_room (id, id_training, id_room, enabled)

Table training_teacher (id, id_training, id_teacher, enabled)

Я хочу получить список тренингов, которые принадлежатгород с количеством подключенных комнат включения и количеством учителей включения.

Где можно написать условия для полей включения?Это начало моего запроса.

SELECT training.id, 
       training.town , 
       COUNT ( t_r.id_formation),  
       COUNT ( t_t.id_formation)
FROM training
LEFT JOIN training_room t_r
LEFT JOIN training_teacher t_t
WHERE training.town ='X'
GROUP BY training.id

Большое спасибо.

Ответы [ 3 ]

2 голосов
/ 24 августа 2011

Я бы посоветовал вам не присоединяться к таким столам. Как я уже сказал в своем комментарии к ответу StieveG, при объединении таблиц таким образом вы можете получить то, что иногда называют мини- декартовым произведением . Вот иллюстрированное объяснение на тот случай, если оно вам понадобится.

Например, у вас есть 2 строки в training_room, соответствующие строке в training, и 3 строки в training_teacher, соответствующие одной и той же строке training. Сначала объединяется таблица комнаты, и в результате мы получаем два ряда для указанной тренировки. Они содержат две отдельные комнаты, но помните, что они также содержат одинаковое обучение, дублированное.

Почему это важно? Потому что последующее соединение с training_teacher выполняется не только с таблицей тренировок, а с результатом соединения из training с training_room. Просто бывает, что условие соединения содержит только столбец из training, но столбец будет взят из предыдущего объединения, а не из таблицы.

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

Таким образом, в результате одного тренинга будет получено 6 рядов, в которых 2 комнаты будут повторяться 3 раза, а 3 учителя будут повторяться дважды. Соответственно, оба СЧЕТА вернут 6.

Одним из возможных решений может быть простое изменение выражений COUNT следующим образом:

…
COUNT (DISTINCT t_r.id),  
COUNT (DISTINCT t_t.id)
…

Это не помешает объединениям производить декартовы произведения, но, по крайней мере, результаты будут последовательными (при условии, что на тренинге никогда не может быть двухместных комнат или учителей).

Но на вашем месте я, вероятно, решил бы это по-другому, сгруппировав подвыборы и присоединив таблицу training к результатам подвыборов, например:

SELECT
  t.id,
  t.town,
  IFNULL(tr.cnt) AS room_count,
  IFNULL(tt.cnt) AS teacher_count
FROM training AS t

  LEFT JOIN (
    SELECT
      id_training,
      COUNT(*) AS cnt
    FROM training_room
    WHERE enabled = 'true'
    GROUP BY id_training
  ) AS tr ON t.id = tr.id_training

  LEFT JOIN (
    SELECT
      id_training,
      COUNT(*) AS cnt
    FROM training_teacher
    WHERE enabled = 'true'
    GROUP BY id_training
  ) AS tt ON t.id = tt.id_training

WHERE t.town = 'X'
2 голосов
/ 23 августа 2011

Предполагая, что я понял вопрос:

SELECT training.id, 
       training.town , 
       COUNT ( distinct t_r.id),  
       COUNT ( distinct t_t.id)
FROM training t
LEFT JOIN training_room t_r ON t.id = t_r.id_training AND t_r.enabled = 'true'
LEFT JOIN training_teacher t_t ON t.id = t_t.id_training AND t_t.enabled = 'true'
WHERE training.town ='X'
GROUP BY training.id
0 голосов
/ 23 августа 2011

Это должно помочь

SELECT training.id, 
       training.town, 
       COUNT ( SELECT t_r.id_training FROM training_room t_r WHERE t.id = t_r.id_training AND t_r.enabled = 'true') AS training_room_count,  
       COUNT ( SELECT t_t.id_training FROM training_teacher t_t WHERE t.id = t_t.id_training AND t_t.enabled = 'true') AS training_teacher_count
FROM training t
WHERE training.town ='X'

или вы можете сделать (делает то же самое в целом):

SELECT training.id, 
       training.town , 
       COUNT ( t_r.id_training) AS training_room_count,  
       COUNT ( t_t.id_training) AS training_teacher_count
FROM training t
LEFT JOIN training_room t_r ON t.id = t_r.id_training
LEFT JOIN training_teacher t_t ON t.id = t_t.id_training
WHERE training.town ='X'
  AND COALESCE(t_r.enabled, 'true') = 'true'
  AND COALESCE(t_t.enabled, 'true') = 'true'
GROUP BY training.id, training.town
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...