Reputation: 1665
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
Upvotes: 0
Views: 48
Reputation: 2513
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.
Upvotes: 1
Reputation: 521249
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:
Demo here:
Upvotes: 1
Reputation: 883
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;
Upvotes: 0
Reputation: 133370
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'
Upvotes: 0