2010-10-14 1 views
5

Отказ от ответственности: Я - SQL newb, и это для класса, но я действительно мог бы использовать мешок в правильном направлении.Ограничения GROUP BY

У меня есть эти три таблицы:

student(_sid_, sname, sex, age, year, gpa)
section(_dname_, _cno_, _sectno_, pname)
enroll(_sid_, grade, _dname_, _cno_, _sectno_)
(первичные ключи, обозначаемые подчеркиванием)

Я пытаюсь написать Oracle-совместимый запрос SQL, который возвращает таблица с именем студента (student.sname), которая имеет самый высокий уровень gpa в каждом разделе (включая section.cno и section.sectno), а также все остальные атрибуты от section.

Я сумел использовать агрегатный запрос и GROUP BY, чтобы получить максимальный средний балл для каждого раздела:

SELECT MAX(s.gpa), e.cno, e.sectno 
    FROM enroll e, 
     student s 
    WHERE s.sid = e.sid 
GROUP BY e.cno, e.sectno 

Не говоря уже о других section атрибутах, я даже не могу понять, как лавировать на имя студента (student.sname). Если я добавлю его в предложение SELECT, он должен быть включен в GROUP BY, который заполняет остальную часть запроса. Если я использую весь этот запрос внутри предложения или FROM внешнего запроса, я могу получить доступ только к трем полям в таблице, что не так много.

Я знаю, что вы не можете дать мне точный ответ, но любые подсказки будут оценены!

+4

@OMG Ponies: Мне нравится, как вы форматируете запросы. – JoshD

+0

@JoshD: мы все делаем ;-) – zerkms

+0

Вы в основном сказали это. Добавьте таблицу разделов в FROM. Добавьте ограничения в раздел WHERE, чтобы присоединиться к разделу для регистрации. Добавьте столбцы, которые вы хотите видеть в SELECT, и повторите их в GROUP BY. – kevpie

ответ

3

Предполагая, что Oracle 9i +, чтобы получить только один из студентов с самым высоким GPA (в случае связей) используют:

WITH summary AS (
    SELECT e.*, 
      s.name, 
      ROW_NUMBER() OVER(PARTITION BY e.cno, e.sectno 
           ORDER BY s.gpa DESC) AS rank 
    FROM ENROLL e 
    JOIN STUDENT s ON s.sid = e.sid) 
SELECT s.* 
    FROM summary s 
WHERE s.rank = 1 

Non КТР эквивалент:

SELECT s.* 
    FROM (SELECT e.*, 
       s.name, 
       ROW_NUMBER() OVER(PARTITION BY e.cno, e.sectno 
            ORDER BY s.gpa DESC) AS rank 
      FROM ENROLL e 
      JOIN STUDENT s ON s.sid = e.sid) s 
WHERE s.rank = 1 

если вы хотите см. всех учащихся, которые привязаны к GPA, используют:

WITH summary AS (
    SELECT e.*, 
      s.name, 
      DENSE_RANK OVER(PARTITION BY e.cno, e.sectno 
           ORDER BY s.gpa DESC) AS rank 
    FROM ENROLL e 
    JOIN STUDENT s ON s.sid = e.sid) 
SELECT s.* 
    FROM summary s 
WHERE s.rank = 1 
1

Подсказка: учтите, что может быть более одного студента с самым высоким GPA в классе. Внешнему запросу нужны только три поля.

0

Может быть кратчайшим:

SELECT DISTINCT e.cno, e.sectno , e..., 
     FIRST_VALUE(s.sname) OVER 
           (PARTITION BY e.cno, e.sectno ORDER BY s.gpa DESC) 
FROM enroll e, 
    student s 
WHERE s.sid = e.sid 

Или

SELECT A.* 
FROM 
    ( SELECT s._sid, s.sname, e.cno, e.sectno ,..., s.gpa 
       MAX(s.gpa) OVER (PARTITION BY e.cno, e.sectno) AS maxgpa 
     FROM enroll e, 
      student s 
     WHERE s.sid = e.sid 
    ) A 
WHERE A.maxgpa = A.gpa 
0

Вот некоторые указатели: -

  1. Вы на правильном пути с вашей группой По запросу
  2. Это возвращает вы максимальный GPA для каждого раздела на основе полей cno и sectno
  3. Теперь у вас есть значение Max GPA для каждой комбинации cno и sectno.
  4. Используйте эти данные, которые вы имеете в обратном порядке, если вам нравится находить всех студентов, соответствующих этим значениям комбинации. ПОДСКАЗКА: Рассмотрим результаты вашей группы По запросу в виде таблицы и использовать INNER JOIN
  5. Даже если это возможно, что есть больше чем 1 студентов для той же максимальной ГПД, вы все равно получите их все

Надеюсь, что это поможет!

0

Это должно дать вам то, что вы ищете. См. Функцию Oracle RANK() для получения подробных сведений о том, как GPA оцениваются с наивысшего наименьшего по разделам.

Требования:

Возвращенные таблица с именем студента (student.sname), который имеет самый высокий средний балл в каждой секции (section.cno и section.sectno), а также все другие атрибуты из раздела ,

SELECT * FROM 
(
    SELECT 
     s.sname, 
     s.gpa, 
     sec.dname, 
     sec.cno, 
     sec.sectno, 
     sec.pname, 
     /* for each "sec.cno, sec.sectno", this will rank each GPA in order from highest to lowest. Ties will have the same rank. */ 
     RANK() OVER(PARTITION BY sec.cno, sec.sectno ORDER BY s.gpa DESC) as r_rank 
    FROM 
     enroll e, 
     student s, 
     section sec 
    WHERE 
     /* join enroll with student */ 
     s.sid = e.sid 
     /* join section with enroll */ 
     AND sec.dname = e.dname 
     AND sec.cno = e.cno 
     AND sec.sectno = e.sectno 
) 
WHERE r_rank = 1 /* this returns only the highest GPA (maybe multiple students) for each "sec.cno, sec.sectno" combination */ 
; 

Примечание: Если вы не хотите связей, изменение RANK() в ROW_NUMBER()

0

Хотя это ответил долго назад, но до сих пор я хочу представить beautiful explanation, это очень полезно для новичков. Также у Introduction to SQL есть такие правила.