SQL-запрос, чтобы определить, имеет ли одна таблица больше строк с атрибутом, чем другая - PullRequest
0 голосов
/ 18 марта 2012

У меня проблемы с домашним заданием:

Найдите все кафедры с большим количеством профессоров, чем студентов.

Включены следующие таблицы:

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

Как я должен это сделать? Я не ищу полный ответ, но намекает на то, как структурировать запрос. Я использую PostgreSQL 9.1.3 на Windows 7.

Редактировать: Спасибо за вашу помощь. Правильный ответ таков:

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: Есть лучшее решение. Я принял ответ, содержащий это решение.

Ответы [ 3 ]

2 голосов
/ 19 марта 2012

Найдите все кафедры с большим количеством профессоров, чем студентов.

Рассмотрим это:

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 голосов
/ 20 марта 2012

Альтернативное решение использует представления:

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;

Этот код правильно обрабатывает случай, когда на данном факультете нет профессоров или студентов.

0 голосов
/ 19 марта 2012

Часть вашего первого запроса, которая вызывает ошибку:

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
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...