Postgresql SQL查询,以确定一个表是否具有比另一个表更多的属性行

Postgresql SQL查询,以确定一个表是否具有比另一个表更多的属性行,postgresql,join,group-by,aggregate-functions,Postgresql,Join,Group By,Aggregate Functions,我的家庭作业练习有问题,如下所示: Table "university.prof" Column | Type | Modifiers -----------+-----------------------+----------- pnum | character(9) | not null lastname | character varying(12) | not null firstname | characte

我的家庭作业练习有问题,如下所示:

Table "university.prof" Column | Type | Modifiers -----------+-----------------------+----------- pnum | character(9) | not null lastname | character varying(12) | not null firstname | character varying(12) | dept | character(4) | office | character(6) | rank | character(1) | date_emp | date | not null salary | numeric(8,2) | manager | character(9) | Indexes: "prof_pkey" PRIMARY KEY, btree (pnum) Table "university.student" Column | Type | Modifiers -----------+---------------+----------- snum | character(9) | not null lastname | character(12) | firstname | character(12) | dept | character(4) | date_ent | date | cr_comp | smallint | gpa | numeric(4,3) | advisor | character(9) | Indexes: "student_pkey" PRIMARY KEY, btree (snum) SET search_path TO university; SELECT prof.dept FROM prof, student WHERE prof.dept = student.dept GROUP BY prof.dept HAVING count(DISTINCT prof.*) > count(DISTINCT student.*); 找到教授多于学生的所有系

所涉及的表格如下:

Table "university.prof" Column | Type | Modifiers -----------+-----------------------+----------- pnum | character(9) | not null lastname | character varying(12) | not null firstname | character varying(12) | dept | character(4) | office | character(6) | rank | character(1) | date_emp | date | not null salary | numeric(8,2) | manager | character(9) | Indexes: "prof_pkey" PRIMARY KEY, btree (pnum) Table "university.student" Column | Type | Modifiers -----------+---------------+----------- snum | character(9) | not null lastname | character(12) | firstname | character(12) | dept | character(4) | date_ent | date | cr_comp | smallint | gpa | numeric(4,3) | advisor | character(9) | Indexes: "student_pkey" PRIMARY KEY, btree (snum) SET search_path TO university; SELECT prof.dept FROM prof, student WHERE prof.dept = student.dept GROUP BY prof.dept HAVING count(DISTINCT prof.*) > count(DISTINCT student.*); 这个问题本质上要求提供一个值列表,其中左表的值行比右表的多。我该怎么做?此查询不起作用:

SET search_path TO university; SELECT dept FROM prof GROUP BY dept HAVING count(*) > ( SELECT count(*) FROM student GROUP BY dept ); 导致以下错误:

ERROR: more than one row returned by a subquery used as an expression
SELECT dept
FROM prof
GROUP BY dept
HAVING count(*) > (
    SELECT count(*) /* This subquery would yield rows equal to no of different  
    FROM student        Department to which students belong.
    GROUP BY dept       Thus you can't compare it with > symbol.*/      
);
此代码也不起作用,导致没有返回行。正确答案返回两行:

SET search_path TO university; SELECT prof.dept FROM prof, student GROUP BY prof.dept HAVING count(prof.*) > count(student.*); 我该怎么做?我不是在寻找完整的答案,而是关于如何构造查询的提示。我正在Windows 7上使用PostgreSQL 9.1.3

编辑:谢谢你的帮助。正确答案如下:

Table "university.prof" Column | Type | Modifiers -----------+-----------------------+----------- pnum | character(9) | not null lastname | character varying(12) | not null firstname | character varying(12) | dept | character(4) | office | character(6) | rank | character(1) | date_emp | date | not null salary | numeric(8,2) | manager | character(9) | Indexes: "prof_pkey" PRIMARY KEY, btree (pnum) Table "university.student" Column | Type | Modifiers -----------+---------------+----------- snum | character(9) | not null lastname | character(12) | firstname | character(12) | dept | character(4) | date_ent | date | cr_comp | smallint | gpa | numeric(4,3) | advisor | character(9) | Indexes: "student_pkey" PRIMARY KEY, btree (snum) SET search_path TO university; SELECT prof.dept FROM prof, student WHERE prof.dept = student.dept GROUP BY prof.dept HAVING count(DISTINCT prof.*) > count(DISTINCT student.*);
编辑2:有更好的解决方案。我已接受包含此解决方案的答案。

您第一次查询中导致错误的部分:

ERROR: more than one row returned by a subquery used as an expression
SELECT dept
FROM prof
GROUP BY dept
HAVING count(*) > (
    SELECT count(*) /* This subquery would yield rows equal to no of different  
    FROM student        Department to which students belong.
    GROUP BY dept       Thus you can't compare it with > symbol.*/      
);
相反,您必须遍历选择的教授表,并为每个教授计算该系的教授人数,然后相应地找到与上述教授属于同一系的学生。 大概是这样的:

select t.prof from prof t where
(
select count(*) from prof where dept=t.dept
)
>
(
select count(*) from student where dept=t.dept
)
找到教授多于学生的所有系

考虑一下这一点:

SELECT p.dept, p.prof_ct, s.stud_ct
FROM (
   SELECT dept, count(*) AS prof_ct
   FROM   university.prof
   GROUP  BY dept
   ) p
LEFT JOIN (
   SELECT dept, count(*) AS stud_ct
   FROM   university.student
   GROUP  BY dept
   ) s USING (dept)
WHERE p.prof_ct >= s.stud_ct OR s.stud_ct IS NULL
ORDER BY p.dept;
应该比你现在的解决方案快得多,因为学生和教授在数量级联接之前就被计算出来了


它还观察到一个系没有学生的情况,而您的解决方案目前忽略了这一点。交叉联接消除了所有没有学生或教授的系。

另一种解决方案使用视图:

根据需要创建或替换临时视图p 选择dept,count*num 来自教授 按部门分组 ; 根据需要创建或替换临时视图 选择dept,count*num 来自学生 按部门分组 ; 选择不同的p.dept 从p,s 其中p.num>s.num;
此代码正确处理给定部门没有教授或学生的情况。

使用have count*>是最可能的错误原因。第二次尝试将错过一个连接谓词,该谓词按部门连接两个表,其中prof.dept=student.dept和关键字在两个计数中都是不同的,因为这样它会计数教授和学生的重复,总是一样的。