3

我正在使用 PostgreSQL 学习 SQL,并且遇到了有关嵌套聚合函数的问题。

我试图找到拥有最多财产的私人所有者的详细信息,其中我有两个关系,privateowner 和 propertyforrent,propertyforrent 有一个外键,ownwerno。

我怀疑我的问题是我试图嵌套聚合函数,但我看不到解决方法。

注意:- 我使用的数据库在 propertyforrent 中的属性 ownwerno 中有错字,它应该是 ownerno。

我尝试使用的代码如下所示~:-

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)));

其伴随的错误如下:-

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

任何见解都会很棒。

4

3 回答 3

5

PostgreSQL 9.1 架构设置

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);

查询 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) )

结果

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

在 SQL Fiddle 上看到这个


受@araqnid 的回答 (+1) 的启发,这是另一个具有窗口功能的变体:

查询

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

结果

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

在 SQL Fiddle 上看到这个

于 2012-11-30T15:13:34.327 回答
2

问题是您不能嵌套聚合函数。

你想要的是更像下面的东西:

SELECT o.fname, o.lname, telno
FROM privateowner o
WHERE o.ownerno = (SELECT p.ownwerno
                   FROM propertyforrent p
                   GROUP BY p.owerno
                   order by COUNT(*)
                   limit 1
                  )

但是,我更喜欢使用显式连接的查询:

select o.fname, ollname, o.telno, numProperties
from PrivateOwner o join
     (select p.ownerno, count(*) as numProperties
      from PropertyForRent pft
      group by p.owerno
     ) pfr
     on o.ownerno = pfr.ownerno
order by NumProperties
limit 1

使用连接,您还可以添加属性数量。而且,您还可以选择多个。要获取最大值的所有属性,可以使用以下where子句:

where NumProperties = (select count(*) as NumProperties
                       from PropertyForRent
                       group by owerno
                       order by 1 desc
                       limit 1
                      )
于 2012-11-30T15:13:28.810 回答
2

在这种情况下,窗口函数可以很好地工作,尽管如果您刚刚开始使用 SQL,您可能希望在更熟悉基础知识时再回到这种情况。

select ownerno, fname
from (
    select privateowner.*, rank() over(order by property_count desc)
    from privateowner join (
            select ownerno, count(*) as property_count
            from propertyforrent group by ownerno
        ) owner_stats using (ownerno)
) x
where x.rank = 1
于 2012-11-30T17:29:31.150 回答