0

I have this table which shows the number of 200 and 404 responses from a website for each day. I need to rearrange it so each date is displayed once per row, and the status codes become the columns.

    status     |           date         |  num  
---------------+------------------------+-------
 200 OK        | 2016-07-31 00:00:00+00 | 45516
 404 NOT FOUND | 2016-07-31 00:00:00+00 |   329
 200 OK        | 2016-07-30 00:00:00+00 | 54676
 404 NOT FOUND | 2016-07-30 00:00:00+00 |   397
 200 OK        | 2016-07-29 00:00:00+00 | 54569
 404 NOT FOUND | 2016-07-29 00:00:00+00 |   382
 200 OK        | 2016-07-28 00:00:00+00 | 54404
 404 NOT FOUND | 2016-07-28 00:00:00+00 |   393

What I'm ultimately trying to find out is the percentage of responses which are 404 on each day. Something like select (date.200 / date.404) from mytable

4 Answers 4

1
SELECT
    "date"::date,
    100.0 * SUM(CASE WHEN status LIKE '404%' THEN num ELSE 0 END) / SUM(num) AS percentage
FROM yourTable
GROUP BY "date"::date

Output:

enter image description here

Demo here:

Rextester

Sign up to request clarification or add additional context in comments.

9 Comments

each day, so you may want to group by the date as well.
@ian-campbell The query works fine in the demo. Are you sure that you have the right table name etc.?
None of the percentages should be anywhere close to 50% though.
@ian-campbell They are all 50% using the 8 rows of sample data you provided.
The percentage of 404 codes on July 31 is 0.72%. Dividing 329 by 45516
|
1

What you actually need is called "Pivot Table" and usually it's achieved in Postgres by using "tablefunc" extension https://www.postgresql.org/docs/current/static/tablefunc.html.

But in this simple scenario I'd choose plain SQL approach with "manual pivoting" (like described here http://tapoueh.org/blog/2013/07/simple-case-for-pivoting-in-sql/):

select
  date,
  sum(case when left(status, 3) = '200' then num end) as status200,
  sum(case when left(status, 3) = '404' then num end) as status404
from
  log
group by 1
order by 1 desc;

Notice, that sum() allows you to have multiple records with the same day and same status -- but with your table structure this will also work.

Comments

0

You could use a join

 select a.date, a.num num_200, b.num num_404, a.num num_200/b.num num_404 rate
 from my_table a
 left join my_table b on a.date = b.date  and b.status= '404 NOT FOUND'
 where a.status= '200 OK'

Comments

0

Try this query --

;WITH PivotData
AS (
    SELECT [Date], -- grouping element
        [Status], -- spreading element
        Number -- aggregating element
    FROM StatusEntries
    )
SELECT [Date]
    ,[200 OK]
    ,[404 NOT FOUND]
FROM PivotData
Pivot(Sum(Number) FOR [Status] IN (
            [200 OK]
            ,[404 NOT FOUND]
            )) AS P;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.