Home > front end >  Is there an SQL query where we apply a set of conditions separately for each id?
Is there an SQL query where we apply a set of conditions separately for each id?

Time:04-15

Eg. If we have a table like this exam_score (record_date refers to month when record is taken, Jan = 1, Feb = 2 etc):

student country score record_date
1 US 70 1
2 US 60 2
3 US 80 3
4 IT 60 2
5 IT 100 4
6 BR 80 5

Which SQL query allows me to generate a table where, for each student, we obtain the highest score obtained by fellow students in the same country before him?

So in this case, I should have something like

student country score record_date max_score
1 US 70 1 null (no usa students before him)
2 US 60 2 70 (among students before him, top score is 70)
3 US 80 3 70 (among students before him, top score is 70)
4 IT 60 2 null (no italy students before him)
5 IT 100 4 60
6 BR 80 5 null

Currently my workaround is to use Python together with SQL queries to get what I want, but could we do this with SQL alone? I'm using MySQL, but maybe the database doesn't matter in terms of the SQL query.

CodePudding user response:

You can have SELECT in the column:

select s.*,
    (select max(score)
     from students
     where country = s.country
     and record_date < s.record_date) as max_score
from students s
order by record_date

CodePudding user response:

Schema (MySQL v8.0)

CREATE TABLE exam_score
    (`student` int, `country` varchar(2), `score` int, `record_date` int)
;
    
INSERT INTO exam_score
    (`student`, `country`, `score`, `record_date`)
VALUES
    (1, 'US', 70, 1),
    (2, 'US', 60, 2),
    (3, 'US', 80, 3),
    (4, 'IT', 60, 2),
    (5, 'IT', 100, 4),
    (6, 'BR', 80, 5)
;

Query #1

SELECT student
     , country
     , score
     , record_date
     , MAX(lag_score) OVER (PARTITION BY country ORDER BY record_date) AS max_score
FROM (
  SELECT student
       , country
       , record_date
       , score
       , LAG(score) OVER (PARTITION BY country ORDER BY record_date) AS lag_score
  FROM exam_score
  ) a
ORDER BY student;

Output:

student country score record_date max_score
1 US 70 1
2 US 60 2 70
3 US 80 3 70
4 IT 60 2
5 IT 100 4 60
6 BR 80 5

View on DB Fiddle

  • Related