2012-05-02 3 views
0

У меня есть следующие три таблицы:SQL Max и Double Регистрация

student 
------- 
stnumb 
stname 
gender 
grade 
born 

subject 
------- 
subjnumb 
subjname 
tname 

results 
------- 
stnumb 
subjnumb 
percent 

Мне нужно вернуть highest result and its subject for each student

Пример: Боб Смит, IPT, 92

Два ближе результаты, которые у меня были:

SELECT stname 
    , subjname 
    , highestmark 
FROM (
      SELECT  MAX(results.percent) as "highestmark" 
        , student.stname 
        , subject.subjname 
      FROM  student 
        , subject 
        , results 
      WHERE  results.stnumb  = student.stnumb 
      AND   results.subjnumb = subject.subjnumb 
      GROUP BY stname 
     ) maxresult 

... и ...

SELECT  student.stname as Student 
     , subject.subjname as Subject 
     , results.percent as Mark 
FROM  results 
JOIN  student 
ON   results.stnumb = student.stnumb 
JOIN  subject 
ON   results.subjnumb = subject.subjnumb 
ORDER BY stname 

Может кто-то пожалуйста мне точку в правильном направлении? Я работаю над этим несколько дней и не делаю никаких оснований.

ответ

0

Судя по отсутствующей subjname в GROUP BY, это MySql. MySql не имеет аналитических функций, поэтому вам нужно вызвать более старые формы верхнего уровня 1. Существует версия с производными таблицами с максимальными значениями. Эта таблица используется для фильтрации исходных таблиц:

SELECT  student.stname as Student 
     , subject.subjname as Subject 
     , results.percent as Mark 
FROM  results 
JOIN  student 
ON   results.stnumb = student.stnumb 
JOIN  subject 
ON   results.subjnumb = subject.subjnumb 
JOIN 
(
    SELECT stnumb, MAX(percent) percent 
    FROM results 
    GROUP BY stnumb 
) top1GradePerStudent 
    ON results.stnumb = top1GradePerStudent.stnumb 
AND results.percent = top1GradePerStudent.percent 
ORDER BY stname 

Существует также not exists подход, извлекая только студенческие записи, которые не имеют более высокий процент:

SELECT  student.stname as Student 
     , subject.subjname as Subject 
     , results.percent as Mark 
FROM  results 
JOIN  student 
ON   results.stnumb = student.stnumb 
JOIN  subject 
ON   results.subjnumb = subject.subjnumb 
WHERE  NOT EXISTS 
      (
       SELECT null 
        FROM results r2 
       WHERE r2.stnumb = results.stnumb 
        AND r2.percent > results.percent 
      ) 
ORDER BY stname 

Оба пути будут возвращать связи. Если вам нужно иметь одну запись на одного учащегося, заключите subjname в MAX или MIN, так как все остальные данные в строке будут одинаковыми, поэтому не важно, какой предмет вы выбираете.

P.S. Я не тестировал эти запросы. Там может быть опечатка, но базовый подход правильный.

+0

Mate, Ты ЛЕГЕНДА! Большое спасибо!!! Первый запрос работает абсолютно отлично. Спасибо за помощь. –

0
SELECT pct, subjname, stname 
FROM 
(SELECT r.pct, sub.subjname, std.stname, 
RANK() OVER (PARTITION BY sub.subjname ORDER BY r.pct) as rk 
FROM student std 
INNER JOIN results r ON r.stnumb = std.stnumb 
INNER JOIN subject sub ON sub.subjnumb = r.subjnumb 
GROUP BY sub.subjname, std.stname, r.pct) a 
WHERE rk = 1 
+0

Извините, hkf, это не сработало. Спасибо за помощь. –

+1

«Это не сработало» очень расплывчато, с чем конкретно вы сталкиваетесь? Я проверил запрос в sqlfiddle, и он выполняется. Хотя я не знаю вашей структуры данных, кроме того, что вы предоставили, я не могу сделать предположение о том, что будет «работать». Подход, предложенный мной с помощью «RANK() OVER (PARTION BY ..ORDER BY ..)», - это правильный подход к решению проблемы, которую вы изложили. – hkf

+0

Я знаю, это неопределенно, но я не могу объяснить, почему нет, все, что он делает, когда вы вводите неверный запрос, ничего не возвращает, поэтому проблема может быть в любом месте. Если бы я знал больше, я бы так сказал. –