'get all students who has got more marks than the average marks of that class

I got two tables below called tbl_student where we store students' data like id, name, class, roll no. and age, and tbl_marks where we store marks scored in an exam. -

CREATE TABLE IF NOT EXISTS public.tbl_student
(
    student_id integer NOT NULL GENERATED ALWAYS AS IDENTITY,
    student_name varchar(255) NOT NULL,
    student_class integer,
    student_roll_no integer,
    age integer,
    CONSTRAINT tbl_student_pkey PRIMARY KEY (student_id)
)

and

CREATE TABLE IF NOT EXISTS public.tbl_marks
(
    marks_id integer NOT NULL GENERATED ALWAYS AS IDENTITY,
    student_id integer NOT NULL,
    subject varchar(255),
    marks integer,
    CONSTRAINT tbl_marks_pkey PRIMARY KEY (marks_id)
)

And these are some data for the respective tables:

INSERT INTO
    public.tbl_student (student_name, student_class, student_roll_no, age)
VALUES
    ('John Doe',5,1, 12),
    ('Clark Keny', 5,2, 10),
    ('Ross Barkley', 5, 3, 11),
    ('Frank Lampard', 5, 4, 9),
    ('John Terry', 5, 5, 10),
    ('Peter Parker',6,1, 13),
    ('Tony Stark', 6,2,11),
    ('Bruce Wayne', 6, 3,14),
    ('Johnny Depp', 6, 4,11),
    ('Jackie Chan',7,1,15),
    ('John Wick', 7,2,14),
    ('Indiana Jones', 7, 3,11),
    ('Halley Berry', 7, 4,12),
    ('Jane Doe', 7, 5,15),
    ('Martha Kent', 7, 6,13);

and

INSERT INTO
    public.tbl_marks (student_id, subject, marks)
VALUES
    (1, 'Math' , 79),
    (1, 'Science' , 64),
    (2, 'Math' , 69),
    (2, 'Science' , 72),
    (3, 'Math' , 30),
    (3, 'Science' , 50),
    (4, 'Math' , 77),
    (4, 'Science' , 72),
    (5, 'Math' , 84),
    (5, 'Science' , 88),
    (6, 'Math' , 36),
    (6, 'Science' , 54),
    (7, 'Math' , 55),
    (7, 'Science' , 54),
    (8, 'Math' , 66),
    (8, 'Science' , 78),
    (9, 'Math' , 43),
    (9, 'Science' , 20),
    (10, 'Math' ,87 ),
    (10, 'Science' , 92),
    (11, 'Math' , 68),
    (11, 'Science' , 82),
    (12, 'Math' , 78),
    (12, 'Science' , 93),
    (13, 'Math' , 20),
    (13, 'Science' , 22),
    (14, 'Math' , 40),
    (14, 'Science' , 42),
    (15, 'Math' , 52),
    (15, 'Science' , 62);

Now, I need to get all students in each class who got more marks than the average marks in their respective classes.

I tried it using the RANK() function with the PARTITION BY clause.



Solution 1:[1]

OK, so finding the averages is like this:

    SELECT s.student_class, m.subject, AVG(m.marks) AS average
      FROM tbl_marks m INNER JOIN tbl_student s USING (student_id) 
      GROUP by s.student_class, m.subject

So, we just need to use that as another table in the join:


SELECT DISTINCT s.student_name, s.student_class, m.subject, m.marks
  FROM tbl_marks m 
  INNER JOIN tbl_student s USING (student_id) 
  INNER JOIN (
    SELECT s.student_class, m.subject, AVG(m.marks) AS average
      FROM tbl_marks m INNER JOIN tbl_student s USING (student_id) 
      GROUP by s.student_class, m.subject) x1 
    USING (student_class, subject)
  WHERE m.marks >= x1.average;

Output:

John Doe              5              Math        79        
Clark Keny            5              Math        69        
Clark Keny            5              Science     72        
Frank Lampard         5              Math        77        
Frank Lampard         5              Science     72        
John Terry            5              Math        84        
John Terry            5              Science     88        
Peter Parker          6              Science     54        
Tony Stark            6              Math        55        
Tony Stark            6              Science     54        
Bruce Wayne           6              Math        66        
Bruce Wayne           6              Science     78        
Jackie Chan           7              Math        87        
Jackie Chan           7              Science     92        
John Wick             7              Math        68        
John Wick             7              Science     82        
Indiana Jones         7              Math        78        
Indiana Jones         7              Science     93     

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tim Roberts