从多个表中检索聚合值

时间:2010-10-21 10:52:44

标签: mysql aggregate left-join

我正在尝试从不同的表中获取一些聚合值,但我的问题是它们被错误地返回,即彼此相乘。

我有这些表:

Institutes
----------
ID
name

Conversions
-----------
ID
institute_id
training_id

Trainings
---------
ID
institute_id

我想获得Institute.name,转换次数和培训次数。我可以获取名称和一个聚合值,但是当我尝试获取两个值时,它返回错误的数字,因为它将重复每次训练的所有转换(或反过来)。

我正在使用这个SQL:

SELECT    Institute.id
          ,Institute.name 
          ,Institute.friendly_url
          ,count(Training.`id`) as totalTrainings
          ,count(Conversion.`id`) AS totalConversions
FROM      institutes Institute  
          LEFT JOIN    trainings Training     ON Institute.`id` = Training.`institute_id`       
          LEFT JOIN    conversions Conversion ON Training.`institute_id` =   Conversion.`institute_id`
GROUP BY  1,2,3

我需要稍后添加更多表,使用相同的结构,并且唯一的目的是检索聚合。我可以通过使用多个查询使其工作,但是当我想要过滤数据时,我会遇到无法使用正确的排序,分页和问题的问题。

创建视图是我一直在考虑的解决方案,但我仍然需要一些SQL来创建该视图。

我也试过修补GROUP BY,但无济于事。

更新 我现在在我的联接中使用子查询,这似乎有效。是否有更优化的解决方案?

SELECT    Institute.id
          ,Institute.name 
          ,Institute.friendly_url
          ,Training.total
          ,Conversion.total
FROM      institutes Institute 
          LEFT JOIN (SELECT institute_id, count(id) AS total
                     FROM `trainings`
                     GROUP BY institute_id) AS Training ON Training.institute_id = Institute.id
          LEFT JOIN (SELECT institute_id, count(id) AS total
                     FROM `conversions`
                     GROUP BY institute_id) AS Conversion ON Conversion.institute_id = Institute.id

2 个答案:

答案 0 :(得分:3)

试试吧。做一个单独的子查询是更好的恕我直言。并且看起来更好,更容易阅读查询。

SELECT    
Institute.id  
,Institute.name   
,Institute.friendly_url  
,(SELECT count(Training.`id`) FROM trainings Training WHERE Institute.`id` = Training.`institute_id` LIMIT 1) as totalTrainings   
,(SELECT count(Conversion.`id`) FROM conversions Conversion ON Institute.`id` =   Conversion.`institute_id`  LIMIT 1) AS totalConversions  
FROM institutes Institute

答案 1 :(得分:0)

(意识到这是两年后) 我相信DISTINCT条款中的COUNT可以解决问题。

SELECT    Institute.id
          ,Institute.name 
          ,Institute.friendly_url
          ,count(DISTINCT Training.`id`) as totalTrainings
          ,count(DISTINCT Conversion.`id`) AS totalConversions
FROM      institutes Institute  
          LEFT JOIN    trainings Training     ON Institute.`id` = Training.`institute_id`       
          LEFT JOIN    conversions Conversion ON Training.`institute_id` =   Conversion.`institute_id`
GROUP BY  1,2,3