Reputation: 12892
I have a table like this:
------------------
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
---------------------------
I'm using following query to get above result:
select
error as Error,
count(*) as Count,
100* count(*)/(select count(*) from logs) as Percentage
from logs
group by error;
Is it optimized for the task? If not, what are some other efficient ways I can get that information?
Upvotes: 3
Views: 326
Reputation: 13161
Before you go and try to optimize any query, you should review the execution plan. For example, in MSSQL, the query plan will look something like this:
You can very clearly see two index scans (top and bottom branches to the right of "Nested Loops"). The top branch is performing your count(*)
aggregate to get the total number of rows in the table. This is done once, and the resulting single row containing the count is paired with each of the rows in the bottom branch. The bottom branch is performing the count
aggregate for each group.
So without changing your highly readable query, you likely already have an efficient execution plan.
Upvotes: 0
Reputation: 311468
This query will perform the count(*)
per row. I'd query it once, and cross join it to the individual counts:
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
Upvotes: 2
Reputation: 12485
Not sure what DBMS you're using. If your DBMS allows you to use aggregate functions as window functions (you can do this in Oracle), then you can do the following:
SELECT error, COUNT(*) AS count, 100*COUNT(*)/COUNT(*) OVER ( ) AS percentage
FROM logs
GROUP BY error
(Note that the OVER( ) clause is empty to indicate that the total count is what is wanted.)
Hope this helps.
Upvotes: 0