sql多次计数

时间:2011-08-23 08:57:05

标签: mysql sql

我有对象培训,房间和老师。 培训有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 个答案:

答案 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