问题
I have a table like this:
date(timestamp) Error(integer) someOtherColumns
I have a query to select all the rows for specific date:
SELECT * from table
WHERE date::date = '2010-01-17'
Now I need to count all rows which Error is equal to 0(from that day) and divide it by count of all rows(from that day).
So result should look like this
Date(timestamp) Percentage of failure
2010-01-17 0.30
Database is pretty big, millions of rows..
And it would be great if someone know how to do this for more days - interval from one day to another.
Date(timestamp) Percentage of failure
2010-01-17 0.30
2010-01-18 0.71
and so on
回答1:
what about this (if error
could be only 1 and 0):
select
date,
sum(Error)::numeric / count(Error) as "Percentage of failure"
from Table1
group by date
or, if error
could be any integer:
select
date,
sum(case when Error > 0 then 1 end)::numeric / count(Error) as "Percentage of failure"
from Table1
group by date
Just fount that I've counted not 0
(assumed that error is when Error != 0), and didn't take nulls into accounts (don't know how do you want to treat it). So here's another query which treats nulls as 0 and counts percentage of failure in two opposite ways:
select
date,
round(count(nullif(Error, 0)) / count(*) ::numeric , 2) as "Percentage of failure",
1- round(count(nullif(Error, 0)) / count(*) ::numeric , 2) as "Percentage of failure2"
from Table1
group by date
order by date;
sql fiddle demo
回答2:
try this
select cast(data1.count1 as float)/ cast(data2.count2 as float)
from (
select count(*) as count1 from table date::date = '2010-01-17' and Error = 0) data1,
(select count(*) as count1 from table date::date = '2010-01-17') data2
回答3:
SELECT date
, round(count((error = 0) OR NULL) / count(*)::numeric, 2) AS percent_fail
FROM tbl
GROUP BY 1
ORDER BY 1;
This even works if error
can be NULL
.
-> SQLfiddle demo.
Much more (incl. implications on performance) under this closely related question:
Compute percents from SUM() in the same SELECT sql query
Comparison and benchmark of ways to count in this related answer on dba.SE.
回答4:
You can use generate_series and takes it from there.
Like this:
WITH CTE AS
(
SELECT
m
--,extract('year' FROM m) AS theyear
--,extract('month' FROM m) AS themonth
--,extract('day' FROM m) AS theday
,(SELECT COUNT(*) AS cnt FROM table WHERE date::date = m AND Error = 1) AS data1
,(SELECT COUNT(*) AS cnt FROM table WHERE date::date = m) AS data2
FROM
(
SELECT generate_series('2012-04-01'::date, '2016-01-01'::date, interval '1 day') AS m
) AS g
) -- END OF CTE
SELECT
m
,COALESCE(data1 * 100.0 / NULLIF(data2, 0.0), 0.0) AS ErrorPercentage
FROM CTE
See this for details: How to perform a select query in a DO block?
来源:https://stackoverflow.com/questions/19495096/divide-two-counts-from-one-select