Прежде всего, ваша модель данных усложняет вам задачу.Вам нужен простой способ определения последовательных кварталов. Итак, вам нужна таблица для хранения этой информации с возрастающим шагом: как еще вы ожидаете, что компьютер узнает, что весна 2009 следует за зимой 2008 года?
В любом случае, вот моя версия ваших тестовых данных.Я использую имена, чтобы было легче увидеть, что происходит:
SQL> select s.name as student
2 , c.name as class
3 , q.season||' '||q.year as quarter
4 , q.q_id
5 , c.base_cost
6 from enrolments e
7 join students s
8 on (s.s_id = e.s_id)
9 join classes c
10 on (c.c_id = e.c_id)
11 join quarters q
12 on (q.q_id = c.q_id)
13 order by s.s_id, q.q_id
14 /
STUDENT CLASS QUARTER Q_ID BASE_COST
---------- -------------------- --------------- ---------- ----------
Sheldon Introduction to SQL Spring 2008 100 100
Sheldon Advanced SQL Spring 2009 104 150
Howard Introduction to SQL Spring 2008 100 100
Howard Information Theory Summer 2008 101 75
Rajesh Information Theory Summer 2008 101 75
Leonard Crypto Foundation Autumn 2008 102 120
Leonard PHP for Dummies Winter 2008 103 90
Leonard Advanced SQL Spring 2009 104 150
8 rows selected.
SQL>
Как видите, у меня есть таблица QUARTERS, первичный ключ которой Q_ID увеличивается на единицу в календарном порядке.
Я собираюсь использовать синтаксис Oracle для решения этой проблемы, в частности, аналитическую функцию LAG:
SQL> select s.name as student
2 , c.name as class
3 , q.season||' '||q.year as quarter
4 , q.q_id
5 , c.base_cost
6 , lag (q.q_id) over (partition by s.s_id order by q.q_id) prev_q_id
7 from enrolments e
8 join students s
9 on (s.s_id = e.s_id)
10 join classes c
11 on (c.c_id = e.c_id)
12 join quarters q
13 on (q.q_id = c.q_id)
14 order by s.s_id, q.q_id
15 /
STUDENT CLASS QUARTER Q_ID BASE_COST PREV_Q_ID
---------- -------------------- --------------- ---------- ---------- ----------
Sheldon Introduction to SQL Spring 2008 100 100
Sheldon Advanced SQL Spring 2009 104 150 100
Howard Introduction to SQL Spring 2008 100 100
Howard Information Theory Summer 2008 101 75 100
Rajesh Information Theory Summer 2008 101 75
Leonard Crypto Foundation Autumn 2008 102 120
Leonard PHP for Dummies Winter 2008 103 90 102
Leonard Advanced SQL Spring 2009 104 150 103
8 rows selected.
SQL>
Итак, просматривая столбцы PREV_Q_ID, мы видим, что у Говарда, Шелдона и Леонарда было большечем один курс.Только Леонард прошел три курса.Сравнивая значения в столбцах PREV_Q_ID и Q_ID, мы можем видеть, что два курса Говарда находятся в последовательных кварталах, в то время как Шелдона нет.
Теперь мы можем сделать несколько математических операций:
SQL> select student
2 , class
3 , quarter
4 , base_cost
5 , discount*100 as discount_pct
6 , base_cost - (base_cost*discount) as actual_cost
7 from
8 ( select student
9 , class
10 , quarter
11 , base_cost
12 , case
13 when prev_q_id is not null
14 and q_id - prev_q_id = 1
15 then 0.2
16 else 0
17 end as discount
18 , s_id
19 , q_id
20 from
21 (
22 select s.name as student
23 , c.name as class
24 , q.season||' '||q.year as quarter
25 , q.q_id
26 , c.base_cost
27 , lag (q.q_id) over (partition by s.s_id order by q.q_id) prev_q_id
28 , s.s_id
29 from enrolments e
30 join students s
31 on (s.s_id = e.s_id)
32 join classes c
33 on (c.c_id = e.c_id)
34 join quarters q
35 on (q.q_id = c.q_id)
36 )
37 )
38 order by s_id, q_id
39 /
(искусственный перерыв, чтобы избавиться от необходимости прокручивать страницу вниз, чтобы увидеть результаты)
STUDENT CLASS QUARTER BASE_COST DISCOUNT_PCT ACTUAL_COST
---------- -------------------- ----------- ---------- ------------ -----------
Sheldon Introduction to SQL Spring 2008 100 0 100
Sheldon Advanced SQL Spring 2009 150 0 150
Howard Introduction to SQL Spring 2008 100 0 100
Howard Information Theory Summer 2008 75 20 60
Rajesh Information Theory Summer 2008 75 0 75
Leonard Crypto Foundation Autumn 2008 120 0 120
Leonard PHP for Dummies Winter 2008 90 20 72
Leonard Advanced SQL Spring 2009 150 20 120
8 rows selected.
SQL>
Итак, Говард иЛеонард получает скидки на свои занятия, а Шелдон и Радж этого не делают.