how to solve the issue with group by and aggregate function in postgresql

拟墨画扇 提交于 2019-12-10 18:19:24

问题


I am trying to write a query for dividing the two SQL statements but it shows me

 ERROR: column "temp.missed" must appear in the GROUP BY clause or be used in 
 an aggregate function
  SQL state: 42803

although when I do group by temp.missed, it seems to be working but shows wrong results because of multiple group by.

I have following tables in PostgreSQL

 create table test.appointments (
      appointment_id serial
      , patient_id integer references test.patients(id)
      , doctor_id integer references test.doctors(id)
      , appointment_time timestamp
      , appointment_status enum('scheduled','completed','missed')
      );

 create table test.visits (
      visit_id serial
      , patient_id integer references test.patients(id)
      , doctor_id integer references test.doctors(id)
      , walk_in_visit boolean
      , arrival_time timestamp
      , seen_time timestamp
      );

I have written following query for finding Missed appointment rate (missed appointments / total appointments) but its shows the above mentioned error.

  select tem.doctor_id, (temp.missed::float/tem.total) as ratio from 
    (select doctor_id, count(appointment_status) as missed from appointments 
     where appointment_status='missed' group by doctor_id)as temp
      join (select doctor_id, count(appointment_status) as total from 
      appointments group by doctor_id) as tem  on temp.doctor_id = 
       tem.doctor_id group by tem.doctor_id;

回答1:


You don't need all those subqueries - a count function applied to a case expression would be much simpler:

SELECT   doctor_id, 
         COUNT(CASE appointment_status 
                    WHEN 'missed' THEN 1 
                    ELSE NULL 
               END)::float / 
         COUNT(*) AS ratio
FROM     appointments
GROUP BY doctor_id



回答2:


You can simplify the query a lot and if you are using PostgreSQL 9.4 you can use a very nice and clear syntax:

SELECT   doctor_id, 
     COUNT(appointment_status)::float
       FILTER (WHERE appointment_status='missed') / 
     COUNT(*) AS ratio
FROM     appointments
GROUP BY doctor_id

The FILTER will affect only the COUNT it is after, so in this case it will only count missed appointments.



来源:https://stackoverflow.com/questions/30431574/how-to-solve-the-issue-with-group-by-and-aggregate-function-in-postgresql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!