优化百分比计算SQL查询

时间:2014-11-13 20:49:15

标签: mysql sql aggregate-functions

我有一张这样的表:

------------------
sl no | Error type
------------------
1     | err1
------------------
2     | err2
------------------
3     | err1
------------------
4     | err2
------------------
5     | err2
------------------
6     | err3
------------------

我想要的结果:

---------------------------
Error type | Count | %
---------------------------
err1       | 2     | 33.33
---------------------------
err2       | 3     | 50
---------------------------
err3       | 1     | 16.66
---------------------------

我正在使用以下查询来获得上述结果:

select 
    error as Error,
    count(*) as Count, 
    100* count(*)/(select count(*) from logs) as Percentage 
from logs 
group by error;

它是否针对任务进行了优化?如果没有,我可以通过哪些其他有效方式获取这些信息?

3 个答案:

答案 0 :(得分:2)

此查询将每行执行count(*)。我查询一次,然后将其加入个人计数:

SELECT     a.error, a.cnt, 100 * a.cnt / b.total_count AS percentage
FROM       (SELECT   error, COUNT(*) as cnt
            FROM     logs
            GROUP BY error) a
CROSS JOIN (SELECT COUNT(*) AS total_count FROM logs) b

答案 1 :(得分:0)

不确定您使用的DBMS。如果您的DBMS允许您使用聚合函数作为窗口函数(您可以在Oracle中执行此操作),那么您可以执行以下操作:

SELECT error, COUNT(*) AS count, 100*COUNT(*)/COUNT(*) OVER ( ) AS percentage
  FROM logs
 GROUP BY error

(注意,OVER()子句为空,表示总计数是想要的。)

希望这有帮助。

答案 2 :(得分:0)

在您尝试优化任何查询之前,您应该查看执行计划。例如,在MSSQL中,查询计划将如下所示:

Query Plan

您可以非常清楚地看到两个索引扫描("嵌套循环"右侧的顶部和底部分支)。顶部分支正在执行count(*)聚合以获取表中的总行数。这样做一次,包含计数的结果单行与底部分支中的每一行配对。底部分支正在为每个组执行count聚合。

因此,如果不更改高度可读的查询,您可能已经有了一个有效的执行计划。