我有对象培训,房间和老师。 培训有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
非常感谢。
答案 0 :(得分:2)
假设我已经理解了这个问题:
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
答案 1 :(得分:2)
我建议你不要那样加入你的牌桌。正如我在对StieveG的答案的评论中所说的那样,通过以这种方式加入表格,你可以得到有时被称为迷你的东西 - Cartesian product。这是一个说明性的解释,以防万一你需要它。
例如,training_room
中有2行与training
中的行匹配,而training_teacher
中的3行匹配相同的training
行。首先将房间表连接起来,结果,我们得到两行用于所述训练。它们包含两个不同的房间,但请记住它们也包含相同的培训,重复。
为什么这很重要?因为training_teacher
的后续加入仅针对培训表而非,而是针对training
的加入的结果{{1 }}。仅发生连接条件仅包含training_room
中的列,但该列将从前一个连接中获取,而不是完全来自该表。
所以,你将匹配每个重复的培训,每个培训你将得到另外三个,匹配教师的数量。
所以,最后,一次训练将产生6行,其中2个房间将重复3次,3名教师将重复两次。因此,两个COUNT都将返回training
。
一种可能的解决方案可能就是简单地更改COUNT表达式,如下所示:
6
这不会阻止连接产生笛卡尔积,但至少结果是一致的(假设培训永远不会有重复的房间或教师)。
但如果我是你,我可能会以不同的方式解决它,通过分组子选择并将…
COUNT (DISTINCT t_r.id),
COUNT (DISTINCT t_t.id)
…
表加入子选择的结果,如下所示:
training
答案 2 :(得分:0)
这应该有帮助
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