我在做家庭作业时遇到问题如下:
找到所有教授比学生更多的部门。
所涉及的表格如下:
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 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
此代码也不起作用,导致没有返回任何行(正确的答案返回两行):
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。
修改:感谢您的帮助。正确答案如下:
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:有一个更好的解决方案。我接受了包含此解决方案的答案。
答案 0 :(得分:2)
找到所有教授比学生更多的部门。
考虑一下这个:
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;
比现在的解决方案快得多,因为学生和教授在dept
之前加入的数量较少(按数量级)加起来计算。
它还观察到某个部门没有学生的情况,您的解决方案目前缺少这种情况。您的交叉联接会消除没有学生(或教授)的所有部门。
答案 1 :(得分:0)
导致错误的第一个查询的一部分:
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.*/
);
相反,你必须遍历professor
表(选择的)并且每位教授计算该部门的教授的数量,然后相应地找到属于同一部分的学生系上述教授。
像这样:
select t.prof from prof t where
(
select count(*) from prof where dept=t.dept
)
>
(
select count(*) from student where dept=t.dept
)
答案 2 :(得分:0)
替代解决方案使用视图:
CREATE OR REPLACE TEMPORARY VIEW p AS ( SELECT dept, count(*) num FROM prof GROUP BY dept ); CREATE OR REPLACE TEMPORARY VIEW s AS ( SELECT dept, count(*) num FROM student GROUP BY dept ); SELECT DISTINCT p.dept FROM p, s WHERE p.num > s.num;
此代码正确处理了某个部门没有教授或学生的情况。