2015-09-13 83 views
0

我有一个由(column_a,column_b)分组并查询聚合值的查询。然后,我想通过column_a进行分组,并获得以前汇总值的总和。SQL:如何使用GROUP BY获取聚合的聚合?

用一个例子可能更清楚:

我们有3个表:项目开发者和贡献者。每个项目都有很多的贡献者,每个开发是一个贡献者许多项目:

+======== projects =========+ +====== devs =======+ 
+--------------+------------+ +--------+----------+ 
| project_name | project_id | | dev_id | dev_name | 
+--------------+------------+ +--------+----------+ 
| parsalot  |   1 | |  1 | Ally  | 
| vimplug  |   2 | |  2 | Ben  | 
| gamify  |   3 | |  3 | Chris | 
+--------------+------------+ +--------+----------+ 
       +==== contributors ===+ 
       +------------+--------+ 
       | project_id | dev_id | 
       +------------+--------+ 
       |   1 |  2 | 
       |   1 |  3 | 
       |   2 |  1 | 
       |   2 |  2 | 
       |   3 |  3 | 
       +------------+--------+ 

我感兴趣的多少工作进入每一个项目。我可以统计每个贡献者的数量,但我希望更多地重视开发人员的贡献,他们不会将时间花在其他项目上。因此,vimplug比parsalot更积极:每个项目都有两个贡献者,但vimplug(Ally)中的一个没有其他任何东西,而parsalot的贡献者都将他们的时间分配到其他项目中。

我已经构造的查询,通过(项目,贡献者)组和计算每个贡献者“奉献”的项目:

SELECT 
    projects.project_name, 
    devs.dev_name, 
    1/COUNT(contributions.project_id) as dedication 
FROM 
    projects 
     JOIN 
    contributors USING (project_id) 
     JOIN 
    devs USING (dev_id) 
     JOIN 
    contributors contributions USING (dev_id) 
GROUP BY projects.project_id , contributors.dev_id; 

它产生,

+--------------+----------+------------+ 
| project_name | dev_name | dedication | 
+--------------+----------+------------+ 
| parsalot  | Ben  |  0.5000 | 
| parsalot  | Chris |  0.5000 | 
| vimplug  | Ally  |  1.0000 | 
| vimplug  | Ben  |  0.5000 | 
| gamify  | Chris |  0.5000 | 
+--------------+----------+------------+ 

我真正想要的是什么但是,是每个项目的总体奉献,即

+--------------+------------------+ 
| project_name | total_dedication | 
+--------------+------------------+ 
| gamify  |   0.5000 | 
| parsalot  |   1.0000 | 
| vimplug  |   1.5000 | 
+--------------+------------------+ 

我(天真地)试图将我的选择语句更改为

SELECT 
    projects.project_name, 
    SUM(1/COUNT(contributions.project_id)) as total_dedication 

但这不起作用(“无效使用组功能”)。有没有办法做到这一点,而不必做一个子选择?

回答

2

只需使用一个子查询:

select project_name, sum(dedication) 
from (<your query here>) q 
group by project_name; 
1

你是接近的解决方案,请使用以下命令:

SELECT project_name,sum(dedication) as total_dedication FROM (SELECT 
    projects.project_name, 
    devs.dev_name, 
    1/COUNT(contributions.project_id) as dedication 
FROM 
    projects 
     JOIN 
    contributors USING (project_id) 
     JOIN 
    devs USING (dev_id) 
     JOIN 
    contributors contributions USING (dev_id) 
GROUP BY projects.project_id , contributors.dev_id) as A GROUP BY project_name 
1

伊万,

你问“有没有一种方法,我可以做这不需要做一个子选择“...是否有一个原因,你不能子选择?

不幸的是,你需要使用子选择,因为你不能合并集合函数(这将是唯一能够完成这个任务的方法)。请参阅:How to combine aggregate functions in MySQL?

因此,如其他答案所示,您必须使用子查询。

+0

我一直希望避免一个子查询,因为我正在使用ActiveRecord在Rails应用程序的上下文中工作。子查询并不是从ORM中抽出的最直接的东西,但我想在这种情况下是不可避免的。无论如何,我需要更好地使用子查询。 – ivan