I have a table similar to:
-----------------------
|Student| Month| GPA |
---------------------
| 1 | 1 | 70 |
| 1 | 2 | 70 |
| 1 | 3 | 75 |
| 2 | 1 | 80 |
| 2 | 2 | 72 |
| 2 | 3 | 72 |
What I want, is to calculate the GPA change, per month, per student - only selecting rows where an actual change was observed. My desired output is:
-----------------------
|Student| Month| GPA |
---------------------
| 1 | 3 | 1.071|
| 2 | 2 | 0.9 |
So far I have the following query (simplified, but similar):
SELECT
Student,
Month,
GPA,
Change =
CASE
WHEN LAG(GPA, 1) OVER (ORDER BY Student, Month) !> 0
THEN 1
WHEN Student != LAG(Student, 1) OVER (ORDER BY Student, Month)
THEN 1
ELSE GPA/LAG(GPA, 1) OVER (ORDER BY Student, Month)
FROM students
ORDER BY Student, Month;
The output I receive from this is:
---------------------------------
|Student| Month| GPA | Change|
---------------------------------
| 1 | 1 | 70 | 1 |
| 1 | 2 | 70 | 1 |
| 1 | 3 | 75 | 1.071|
| 2 | 1 | 80 | 1 |
| 2 | 2 | 72 | 0.9 |
| 2 | 3 | 72 | 1 |
I believe a sub-query is needed to only select rows where Change != 1
, but I'm unsure how to implement this correctly here.
You seem to want:
select s.*,
gpa / nullif(prev_gpa, 0) -- I suppose a 0 gpa is possible
from (select s.*,
lag(gpa) over (partition by student order by month) as prev_gpa
from s
) s
where prev_gpa is not null and prev_gpa <> gpa;
Very similar to Gordon's, but takes advantage of the optional 3rd parameter to LAG to use the current row's GPA when there is no previous (to yield no change).
SELECT *
FROM (
SELECT Student, Month, GPA
, Change = GPA / LAG(GPA, 1, GPA) OVER (PARTITION BY Student ORDER BY Month)
FROM students
) AS subQ
WHERE Change != 1.0
ORDER BY Student, Month
;
Edit: I'm not sure what the minimum GPA value could be, but it is best to be aware that a previous GPA of 0 would cause a divide by zero error.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.