#sql #postgresql #aggregate-functions
#sql #postgresql #агрегатные функции
Вопрос:
У меня есть 2 таблицы, student и qualifications, как указано ниже. Я должен найти сведения обо всех студентах на основе обязательных полей, и порядок записей должен основываться на его оценках, возрасте, самой высокой квалификации, самой низкой квалификации и проценте его самой низкой квалификации.
Я пробовал разные запросы, в которые я включал все необходимые поля. Но предположим, что если у студента 3 квалификации, записи умножаются столько раз. НАПРИМЕР:
Sr.No Student_ID Highest Qualification Marks
1 001 Grad SSC 80
2 001 Grad HSC 60
3 001 Grad Grad 80
4 002 HSC SSC 60
5 002 HSC HSC 50
6 003 SSC SSC 40
Это запрос, который я пробовал
SELECT std.stud_id, std.dob, std.highest_qual, MIN(std.lowest_qual) , std.marks
FROM student std
LEFT JOIN qualifications qual ON std.stud_id = qual.stud_id
Where std.fees_paid ='Y'
ORDER BY std.marks, std.dob, std.highest_qual
Ожидаемый результат:
001 23-04-1991 Grad SSC 80
002 20-09-1992 HSC SSC 60
003 13-05-1992 SSC SSC 40
Результат запроса: запрос возвращает все записи вместо одной записи для каждого студента
001 23-04-1991 Grad SSC 80
001 23-04-1991 Grad HSC 60
001 23-04-1991 Grad GRAD 80
002 20-09-1992 HSC SSC 60
002 20-09-1992 HSC HSC 60
003 13-05-1992 SSC SSC 40
Комментарии:
1. Зачем вы объединяете
qualifications
таблицу, если вы не используете ее в своем запросе?2. я использовал left join, потому что позже мне, возможно, придется использовать несколько полей, отличных от упомянутых выше, а также включать другое условие
3. И как вы узнаете, какая квалификация выше? max () и min () будут использовать сортировку по алфавиту.
Ответ №1:
Я полагаю, что в вашей qualifications
таблице есть какой-то индикатор, указывающий ранг для данной квалификации (скажем qual_rank
). Если это так, вы можете сделать
select * from
( select s.*, row_number() OVER ( partition by student_id
order by q.qual_rank ) as rn
from student s join qualifications qual ON std.stud_id = qual.stud_id
) sq where rn = 1;
Если нет, вы должны определить иерархию
select * from
( select s.*, row_number() OVER ( partition by student_id order by
CASE qualification WHEN 'SSC' THEN 1
WHEN 'HSC' THEN 2
WHEN 'Grad' THEN 3
END
) as rn
from student s) sq where rn = 1;
Комментарии:
1. предположим, что 2-й кандидат обучался на дому и непосредственно имеет свою самую низкую квалификацию в записях как HSC вместо SSC. Будет ли это иметь какое-либо значение для записей?
2. @PrajaktaKalghatgi : Вы пробовали его использовать? Что вы ожидаете увидеть в этом случае SSC или HSC?
3. если самая высокая квалификация — HSC, то HSC должен отображаться для этого студента и SSC для других студентов.
4. @PrajaktaKalghatgi : Это будет работать так, как ожидалось, посмотрите это и запишите результат для
student_id
3. Почему бы вам не попробовать и не сообщить мне, если это не сработает?
Ответ №2:
Я бы предположил, что структура таблицы будет такой, и я упомянул запрос для этой структуры.
CREATE TABLE student(Id integer PRIMARY KEY, Name text);
INSERT INTO student VALUES(1,'Tom');
INSERT INTO student VALUES(2,'Lucy');
INSERT INTO student VALUES(3,'Frank');
INSERT INTO student VALUES(4,'Jane');
INSERT INTO student VALUES(5,'Robert');
CREATE TABLE Qualifications(Id integer PRIMARY KEY, qualification_text text, qualification_level integer);
INSERT INTO Qualifications VALUES(1,'SSC',1);
INSERT INTO Qualifications VALUES(2,'HSC',2);
INSERT INTO Qualifications VALUES(3,'Grad',3);
CREATE TABLE StudentQualifications(student_id integer, qualification_id integer, marks float);
INSERT INTO StudentQualifications VALUES(1,1,80);
INSERT INTO StudentQualifications VALUES(1,2,90);
INSERT INTO StudentQualifications VALUES(1,3,90);
INSERT INTO StudentQualifications VALUES(2,1,75);
INSERT INTO StudentQualifications VALUES(3,1,70);
SELECT result.Name, highest.qualification_text, highest_marks.marks,lowest.qualification_text,lowest_marks.marks FROM
(SELECT Std.name AS Name,Std.Id AS stud_id, MAX(q.qualification_level) AS
highest,MIN(q.qualification_level) AS lowest
FROM
student std
LEFT JOIN
StudentQualifications sq
ON
std.id = sq.student_id
INNER JOIN
Qualifications q
ON
sq.qualification_id = q.Id
GROUP BY std.Name, std.Id) result
INNER JOIN
Qualifications highest
ON
highest.qualification_level = result.highest
INNER JOIN
Qualifications lowest
ON
lowest.qualification_level = result.lowest
INNER JOIN
StudentQualifications highest_marks
ON
highest.id = highest_marks.qualification_id
AND
result.stud_id = highest_marks.student_id
INNER JOIN
StudentQualifications lowest_marks
ON
lowest.id = lowest_marks.qualification_id
AND
result.stud_id = lowest_marks.student_id;
Возможно, вам потребуется изменить ВНУТРЕННИЕ СОЕДИНЕНИЯ на ЛЕВЫЕ СОЕДИНЕНИЯ на основе данных и выходных данных, которые вы предпочитаете.
Комментарии:
1. результатом этого запроса будет только самая высокая и самая низкая квалификация. Как я могу получить оценки самой низкой квалификации?
2. Вы можете просто отредактировать последний запрос, чтобы снова объединить с StudentQualifications, чтобы получить оценки:
3. Сейчас я отредактировал ответ. Надеюсь, это сработает для вас