4

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
quin16
  • 515
  • 2
  • 8
  • 15

4 Answers4

6

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

Roman Pekar
  • 107,110
  • 28
  • 195
  • 197
3

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
Apostolos
  • 10,033
  • 5
  • 24
  • 39
1
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.

Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • @quin61: Be sure to follow the links for information on performance. `count(*)` is a bit faster than `count(col)` and also safe against NULL values. Strictly speaking, Roman's answer is incorrect as long we don't know whether the column can be NULL. – Erwin Brandstetter Oct 21 '13 at 17:46
0

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?

Community
  • 1
  • 1
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442