2012-03-18 67 views
0

我有如下一個課外練習麻煩的屬性更多的行:SQL查詢,以確定是否一個表具有比其他

Find all departments with more professors than students.

涉及的表如下:

 
      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

使用'HAVING count(*)>('是最可能的錯誤原因。 – hjpotter92 2012-03-18 20:00:14

+1

第二次嘗試錯過了按部門連接兩個表的連接謂詞 - **,其中prof.dept = student.dept **和關鍵字** distinct **,因爲這種方法可以統計教授和學生的重複次數,它總是一樣。 – 2012-03-18 20:26:46

回答

1

Find all departments with more professors than students.

考慮這樣一個:

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加入製成。

它也觀察部門有沒有學生,您的解決方案目前錯過的情況。你的交叉聯合消除了沒有學生(或教授)的所有部門。

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

此代碼正確地處理那裏有一個給定的部門沒有教授或學生的情況。

相關問題