MySQL:聚合聚合值

时间:2013-08-14 22:27:04

标签: mysql subquery aggregate-functions

考虑这个简单的查询:

SELECT 
    year(t.date) AS y, 
    month(t.date) AS m, 
    t.person_id AS id, 
    count(*) AS freq
FROM 
    table t
WHERE 
    t.date>='2013-01-01' AND t.date<='2013-06-30'
GROUP BY y, m, id

这产生了这样的结果:

y     m  id   freq
------------------
2013  1  100  2
2013  1  101  7
2013  1  102  1
2013  2  100  5
2013  2  101  4
2013  2  102  11
...

我想添加一个列,其中包含每个月频率总和的频率百分比,例如:

y     m  id   freq perc
-----------------------
2013  1  100  2    20
2013  1  101  7    70
2013  1  102  1    10
2013  2  100  5    25
2013  2  101  4    20
2013  2  102  11   55
...

到目前为止,我的解决方案是将其添加到select子句中:

count(*) * 100 / (SELECT count(*) FROM table WHERE year(date)=y AND month(date)=m) AS perc

但我想避免使用子选择,特别是因为所有必要的值都已存在于第一个查询的结果中。这需要汇总聚合值,但我不知道如何做到这一点。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

SELECT 
    year(t.date) AS y, 
    month(t.date) AS m, 
    t.person_id AS id, 
    COUNT(*) AS freq,
    CASE WHEN p.freq = 0 then 0
         ELSE (CAST(COUNT(*) as FLOAT) / p.freq) * 100 
         END AS rate
FROM table t
JOIN (
    SELECT 
        year(t.date) AS y, 
        month(t.date) AS m,  
        count(*) AS freq
    FROM table
    GROUP BY y, m
) p ON p.y = year (t.date) AND p.m = month (t.date)
WHERE t.date BETWEEN '2013-01-01' AND '2013-06-30'
GROUP BY y, m, id

答案 1 :(得分:0)

如果没有你提出的那种子查询,MySQL就无法做到这一点。但是,要使数字添加到100%,您应该小心确保查询的分母包含与分子兼容的WHERE子句。

在您提出的解决方案中,您不会得到总计100%。

使用您建议的查询而不添加其他列

SELECT 
    year(t.date) AS y, 
    month(t.date) AS m, 
    t.person_id AS id, 
    count(*) AS freq
FROM 
    table t
WHERE 
    t.date>='2013-01-01' AND t.date<='2013-06-30'
GROUP BY y, m, id

作为起点,您想要的最终查询是:

SELECT 
    year(t.date) AS y, 
    month(t.date) AS m, 
    t.person_id AS id, 
    count(*) AS freq,
    (count(*) * 100) / 
        (
            select count(*) 
            from table t 
            where t.date>='2013-01-01' 
            AND t.date<='2013-06-30'
        )
FROM 
    table t
WHERE 
    t.date>='2013-01-01' AND t.date<='2013-06-30'
GROUP BY y, m, id

我建议使用已知问题的查询表(称为表)将产生错误。在我做的小测试中,我将其重命名为t1。通常,调用表'table'是不可移植的。