How to solve the problem with group and aggregate function in postgresql

I am trying to write a query to divide 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 group by temp.missed it seems to work but shows incorrect results due to multiple groups.

I have the 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 wrote the following query to find a missed appointment date (missed appointments / general appointments), but it has the above 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;

      

+3


source to share


2 answers


You don't need all these subqueries - the function count

applied to the expression case

will 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

      

+1


source


You can simplify your query, 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

      



FILTER

will only affect COUNT

after, so in this case it will only count missed appointments.

+1


source







All Articles