Как правильно использовать групповое предложение в MySQL с несколькими условиями? - PullRequest
0 голосов
/ 28 февраля 2019

Я пишу запрос, который найдет самого младшего ученика по каждой специальности, если их средний балл превышает 80, и упорядочит их по имени из следующего соотношения.Я использую сервер MySQL и работаю с MySQL Workbench.

Ученик :

snum: integer
name: string
major: string
level: string
age: integer

Класс :

cname: string
meets_at: time
room: string
fid: integer

Оценка :

snum (foreign key)
name (foreign key)
score 

Вот как я пытался реализовать запрос.

select S.major, S.name, S.age
from student S , grades G
group by S.major
Having MIN(S.age) and G.score > (Select avg(G.score) 
                                from grades G1 , student S
                                where S.snum = G1.snum) ;

Однако это не работает, и я действительно запутался в том, как должен выглядеть запрос.

Пример данных:

CREATE TABLE students
(`snum` int, `name` varchar(18), `major` varchar(22), `standing` varchar(2), 
`age` int)
 ;

INSERT INTO student
(`snum`, `name`, `major`, `standing`, `age`)
VALUES
(578875478, 'Edward Baker', 'Veterinary Medicine', 'SR', 21),
(574489456, 'Betty Adams', 'Economics', 'JR', 20),
(573284895, 'Steven Green', 'Kinesiology', 'SO', 19),
(567354612, 'Karen Scott', 'Computer Engineering', 'FR', 18),
(556784565, 'Kenneth Hill', 'Civil Engineering', 'SR', 21),
(552455318, 'Ana Lopez', 'Computer Engineering', 'SR', 19),
(550156548, 'George Wright', 'Education', 'SR', 21),
(462156489, 'Donald King', 'Mechanical Engineering', 'SO', 19),
(455798411, 'Luis Hernandez', 'Electrical Engineering', 'FR', 17),
(451519864, 'Mark Young', 'Finance', 'FR', 18),
(351565322, 'Nancy Allen', 'Accounting', 'JR', 19),
(348121549, 'Paul Hall', 'Computer Science', 'JR', 18),
(322654189, 'Lisa Walker', 'Computer Science', 'SO', 17),
(320874981, 'Daniel Lee', 'Electrical Engineering', 'FR', 17),
(318548912, 'Dorthy Lewis', 'Finance', 'FR', 18),
(301221823, 'Juan Rodriguez', 'Psychology', 'JR', 20),
(280158572, 'Margaret Clark', 'Animal Science', 'FR', 18),
(269734834, 'Thomas Robinson', 'Psychology', 'SO', 18),
(132977562, 'Angela Martinez', 'History', 'SR', 20),
(115987938, 'Christopher Garcia', 'Computer Science', 'JR', 20),
(112348546, 'Joseph Thompson', 'Computer Science', 'SO', 19),
(99354543, 'Susan Martin', 'Law', 'JR', 20),
(60839453, 'Charles Harris', 'Architecture', 'SR', 22),
(51135593, 'Maria White', 'English', 'SR', 21);

CREATE TABLE grades
(`snum` int, `cname` varchar(23), `score` int);

INSERT INTO grades
(`snum`, `cname`, `score`)
VALUES
(574489456, 'Urban Economics', 45),
(567354612, 'Operating System Design', 98),
(567354612, 'Data Structures', 100),
(552455318, 'Operating System Design', 98),
(552455318, 'Communication Networks', 87),
(455798411, 'Operating System Design', 100),
(455798411, 'Optical Electronics', 87),
(348121549, 'Database Systems', 90),
(322654189, 'Database Systems', 97),
(322654189, 'Operating System Design', 56),
(301221823, 'Perception', 87),
(301221823, 'Social Cognition', 87),
(115987938, 'Database Systems', 100),
(115987938, 'Operating System Design', 98),
(112348546, 'Database Systems', 80),
(112348546, 'Operating System Design', 35),
(99354543, 'Patent Law', 65)
 ;

Ожидаемые результаты:

+------------------------+----------------+----+---------+---+
| Computer Engineering   | Karen Scott    | 18 | 99.0000 | 1 |
+------------------------+----------------+----+---------+---+
| Computer Science       | Paul Hall      | 18 | 90.0000 | 1 |
+------------------------+----------------+----+---------+---+
| Electrical Engineering | Luis Hernandez | 17 | 93.5000 | 1 |
+------------------------+----------------+----+---------+---+
| Psychology             | Juan Rodriguez | 20 | 87.0000 | 1 |
+------------------------+----------------+----+---------+---+

1 Ответ

0 голосов
/ 28 февраля 2019

Вот подход, который может работать для вашего варианта использования.Логика состоит в том, чтобы объединить агрегацию и оконные функции .

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

SELECT s.major, s.name, s.age, AVG(g.score) avg_score
FROM 
    students s
    INNER JOIN grades g ON g.snum = s.snum
GROUP BY s.snum, s.major, s.name, s.age
HAVING AVG(g.score) > 80

Это даст вам по одной записи на каждого учащегося, чей средний балл превышает 80, а также его возраст, имя, основной и средний балл.

Теперь осталось только выбратьсамый молодой студент в каждой группе студентов, которые имеют ту же основную.Это можно сделать с помощью оконной функции ROW_NUMBER():

SELECT major, name, age, avg_score
FROM (
    SELECT
        x.*,
        ROW_NUMBER() OVER(PARTITION BY major ORDER BY age) rn
    FROM (
        SELECT s.major, s.name, s.age, AVG(g.score) avg_score
        FROM 
            students s
            INNER JOIN grades g ON g.snum = s.snum
        GROUP BY s.snum, s.major, s.name, s.age
        HAVING AVG(g.score) > 80
    ) x
) z WHERE rn = 1

Это DB Fiddle с вашими примерами возвращаемых данных:

| major                  | name           | age | avg_score |
| ---------------------- | -------------- | --- | --------- |
| Computer Engineering   | Karen Scott    | 18  | 99        |
| Computer Science       | Paul Hall      | 18  | 90        |
| Electrical Engineering | Luis Hernandez | 17  | 93.5      |
| Psychology             | Juan Rodriguez | 20  | 87        |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...