Reputation: 686
I've got one table called Calls with the following fields.
I want to create a view that groups the calls by Week and shows the following columns:
I start with this definition:
CREATE VIEW TotalView AS select
Call.Week,
Count(ID) as TotalCalls
From
Call
GROUP BY
Call.Week;
The Weeks and the TotalCalls show correctly. Then, I try to calculate the calls with satisfaction score with less that 3 but the results are wrong. I enter this statement
...
select
Call.Week,
Count(ID) as TotalCalls,
Count(CallsLess) as CallsLess3
From
Call,
(select ID as CallsLess from Call where SatisfactionRate<3)
GROUP BY
Call.Week
...but the result table is totally wrong and now the TotalCalls column is even wrong.
Upvotes: 0
Views: 47
Reputation: 164069
With conditional aggregation:
select
week,
count(*) totalcalls,
100.0 * sum(case when exittime is null then 1 else 0 end) / count(*) abandonrate,
sum(case when satisfactionrate < 3 then 1 else 0 end) callsless3
from call
group by date_trunc('month', date)::DATE, week
Upvotes: 1
Reputation: 35563
Use "conditional aggregation" by placing case expressions inside the aggregate functions.
CREATE VIEW TotalView AS select
Call.Week,
Count(ID) as TotalCalls,
(Count( case when exit_time is null then 1 end ) * 100.0 ) / count(*) as SatisfactionScore
From
Call
GROUP BY
Call.Week;
To implement non-standard calendars probably requires that you build a calendar table and use that to inform your queries how you have defined weeks to be treated. I have always preferred a week to remain 7 days in leng, anything else is confusing imho.
Upvotes: 0
Reputation: 1269553
Postgres supports the filter
clause, which makes conditional aggregation almost friendly:
select c.Week as call_week,
count(*) as total_calls,
count(*) filter (where c.exittime is null) as abandoned_calls,
avg( (c.exttime is null)::int ) as abandon_rate,
count(*) filter (where c.satisfaction < 3) as low_satisfaction
from call c
group by c.Week;
Upvotes: 1