Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Aggregate Function Nesting

I am learning SQL with PostgreSQL, and have run into a problem regarding nested Aggregate functions.

I am trying to find the details of private owners with the maximum amount of properties, where I have two relations, privateowner and propertyforrent with propertyforrent having a foreign key, ownwerno.

I suspect that my issue is where I am attempting to nest Aggregate Functions, but I cannot see a way around it.

NOTE:- the database I am using has a typo in the attribute ownwerno in propertyforrent, where it should be ownerno.

The code I am attempting to use is shown below~:-

SELECT o.fname, o.lname, telno
FROM privateowner o
WHERE o.ownerno = (SELECT p.ownwerno
           FROM propertyforrent p
           HAVING COUNT(p.ownwerno) = MAX(COUNT(o.ownerno)));

Its accompanying error is as follows:-

ERROR:  column "p.ownwerno" must appear in the GROUP BY clause or be used in a
aggregate function
LINE 3: WHERE o.ownerno = (SELECT p.ownwerno
                                  ^


********** Error **********

ERROR: column "p.ownwerno" must appear in the GROUP BY clause or be used in an
aggregate function
SQL state: 42803
Character: 78

Any insight would be wonderful.

like image 375
Jack H Avatar asked Nov 21 '25 13:11

Jack H


1 Answers

PostgreSQL 9.1 Schema Setup:

create table privateowner(ownerno integer, fname text);
insert into privateowner(ownerno, fname) values (1,'Alice'), 
                                                (2,'Bob'), 
                                                (3,'Charlie');

create table propertyforrent(ownerno integer);
insert into propertyforrent(ownerno) values (1), (2), (2), (3), (3);

Query 1:

with w as ( select ownerno, count(*) as property_count 
            from propertyforrent 
            group by ownerno )
select * 
from privateowner
where ownerno in( select ownerno 
                  from w 
                  where property_count=( select property_count
                                         from w 
                                         order by 1 desc limit 1) )

Results:

| OWNERNO |   FNAME |
---------------------
|       2 |     Bob |
|       3 | Charlie |

see this on SQL Fiddle


inspired by @araqnid's answer (+1), here is another variant with windowing functions:

Query:

select ownerno, fname
from( select ownerno, fname, rank() over (order by count(*) desc) rnk
      from privateowner join propertyforrent using(ownerno) 
      group by ownerno, fname ) z
where rnk=1

Results:

| OWNERNO |   FNAME |
---------------------
|       3 | Charlie |
|       2 |     Bob |

see this on SQL Fiddle


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!