2013-07-23 2 views
0

У меня есть таблица с результатами экзамена, который выглядит следующим образом:Oracle - получить последнюю из подмножества наилучших результатов

CREATE TABLE tbl (
studentid INT, 
examid INT, 
score INT, 
attempt INT, 
percentcorrect INT 
); 

Теперь для каждого студента, мне нужно, чтобы извлечь его лучшие результаты экзаменов (измеряется percentcorrect) , и если данный экзамен был выполнен дважды с тем же самым лучшим показателем для данного учащегося, следует показать запись с последней попыткой. Я сделал это с двойными вложенными запросами (сначала выбирая самый высокий процентный показатель, затем максимальную попытку из результирующего набора, а затем остальные данные), но я надеюсь, что есть более эффективный способ этого. Есть идеи?

EDIT: Мой запрос:

SELECT 
    result.score 
    , r2.attempt 
    , r2.percentcorrect 
    , r2.studentid 
    , r2.examid 
FROM 
    tbl result JOIN 
    (
     SELECT 
      res.studentid 
      , res.examid 
      , r.percentcorrect 
      , MAX(res.attempt) AS attempt 
     FROM 
      tbl res JOIN 
      (
       SELECT studentid, examid, MAX(percentcorrect) AS percentcorrect 
       FROM tbl 
       GROUP BY studentid, examid 
      ) r ON r.studentid = res.studentid 
      AND r.examid = res.examid 
      AND r.percentcorrect = res.percentcorrect 
     GROUP BY 
      res.studentid 
      , res.examid 
      , r.percentcorrect 
     ORDER BY res.examid 
    ) r2 
ON r2.studentid = result.studentid 
AND r2.examid = result.examid 
AND r2.percentcorrect = result.percentcorrect 
AND r2.attempt = result.attempt 

Некоторые образцы данных:

INSERT ALL 
INTO tbl(studentid, examid, percentcorrect, attempt, score) 
VALUES(1,1,30,1,10) 
INTO tbl(studentid, examid, percentcorrect, attempt, score) 
VALUES(1,1,20,2,15) 
INTO tbl(studentid, examid, percentcorrect, attempt, score) 
VALUES(2,1,80,1,100) 
INTO tbl(studentid, examid, percentcorrect, attempt, score) 
VALUES(2,1,80,2,90) 
INTO tbl(studentid, examid, percentcorrect, attempt, score) 
VALUES(3,2,10,1,9) 
INTO tbl(studentid, examid, percentcorrect, attempt, score) 
VALUES(3,3,15,1,100) 
SELECT * FROM DUAL; COMMIT; 
+2

Пожалуйста, ваши вопросы и несколько строк данных образцов. –

ответ

4

Analytical RANK function могут быть использованы для этого:

SELECT studentid, examid, score 
FROM (
    SELECT 
    studentid, 
    examid, 
    score, 
    attempt, 
    RANK() OVER (
     PARTITION BY studentid, examid 
     ORDER BY score DESC, attempt DESC) AS ScoreAttemptRank 
    FROM tbl 
) 
WHERE ScoreAttemptRank = 1 

Этот запрос возвращает лучший результат с последней попыткой на каждого учащегося/на экзамен. Если вам нужен только лучший экзамен для каждого студента, независимо от экзамена, измените PARTITION BY studentid, examid на PARTITION BY studentid.

0

Вы можете использовать выражение таблицы Comman (https://forums.oracle.com/thread/921467) и OVER (http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions137.htm) для достижения результата. Следующий запрос - это w.r.t SQL Server, у нас такие же вещи в Oracle. Кроме того, для определения последнего результата экзамена для того же экзамена я есть ExamDate в таблице

;WITH CTE_StudentResult 
      AS (SELECT StudentId , 
         PercentCorrect , 
         ROW_NUMBER() OVER (PARTITION BY StudentId ORDER BY percentcorrect DESC, ExamDate DESC) AS RowNumber 
       FROM  tbl 
      ) 
    SELECT StudentId , 
      PercentCorrect 
    FROM CTE_StudentResult 
    WHERE RowNumber = 1 
0

Попробуйте

SELECT DISTINCT * FROM tbl 
WHERE (studentid, percentcorrect, attempt) IN (
     SELECT studentid, percentcorrect, MAX (attempt) 
     FROM tbl 
     WHERE (studentid, percentcorrect) IN (SELECT studentid,MAX (percentcorrect)FROM tbl GROUP BY studentid) 
     GROUP BY studentid, percentcorrect) 
Смежные вопросы