优化百分比计算的SQL查询

3

我有这样一张表:

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

Result I want:

---------------------------
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;

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


你关心的是 select count(*) from logs 子查询吗?还是你有其他的疑虑? - undefined
它对你来说运行得够快吗?除非出现问题,否则不必担心效率。 - undefined
@DaveZych 我的表格大约有400万条记录,因此拥有一个高效的解决方案将为我节省大量的时间和金钱。 - undefined
@Abhijeet,4M条记录其实并不算多,除非这些记录非常宽。你的原始查询是正确的,不需要进行交叉连接,除非你想让查询看起来更复杂-请参考我的回答。 - undefined
3个回答

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

这是不正确的,因为在原始查询中count(*)不会针对每一行执行一次。这个操作将在执行计划中被优化掉。 - undefined

0
在你尝试优化任何查询之前,你应该先查看执行计划。例如,在MSSQL中,查询计划会类似于这样:

Query Plan

你可以非常清楚地看到两个索引扫描(在“嵌套循环”右侧的顶部和底部分支)。顶部分支执行count(*)聚合操作,以获取表中的总行数。这只需要执行一次,并且得到的包含计数的单行与底部分支的每一行配对。底部分支为每个组执行count聚合操作。

因此,在不改变你的高可读性查询的情况下,你可能已经拥有了一个高效的执行计划。


谢谢你指出来。我一直以为 'select count(*) from logs' 会对外部表的每一行都运行。 - undefined

0

不确定您使用的是哪种数据库管理系统(DBMS)。如果您的DBMS允许您将聚合函数用作窗口函数(在Oracle中可以这样做),那么您可以执行以下操作:

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

(请注意,OVER()子句为空,表示需要的是总计数。)
希望这可以帮到您。

我正在使用MySQL服务器。:( - undefined
请在以后的提问中尽量正确标记标签...这样可以帮助其他人知道您正在使用哪个数据库管理系统! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接