mysql - SQL查找连续的季度

标签 mysql sql oracle

我想为成员(member)提供该类(class)费用 20% 的折扣 谁在上个季度上过课(如果成员(member)上过 连续三个季度上课,最后两个季度她将获得折扣)。并总结我给出的所有折扣($)。

这是数据库中的表:

注册(class_id、member_id、费用)

CLASS(class_id、season、year)和属性season可以是Spring、Summer、Fall、Winter。

数据看起来像这样:

注册

Class_id  Member_id  Cost
--------  ---------  ----
3         3          20 
1         9          15 
2         9          20 
4         10         30 
3         10         10 
5         5          10 
4         9          30 
...

class_id  Season  Year 
--------  ------  ----
1         Spring  2008 
2         Fall    2008 
3         Spring  2009 
4         Winter  2008 
5         Summer  2008 
...

最佳答案

首先,您的数据模型让您很为难。您需要一种简单的方法来识别连续的季度,因此,您需要一个表来保存该信息,其中一个键是递增的增量:否则您如何期望计算机知道 2009 年 Spring 紧接着 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 列,我们可以看到 Howard、Sheldon 和 Leonard 都上过不止一门类(class)。只有伦纳德上过三门课。通过比较 PREV_Q_ID 和 Q_ID 列中的值,我们可以看到 Howard 的两个类(class)在连续的宿舍中,而 Sheldon 的则不是。

现在我们可以做一些数学运算了:

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>

因此,Howard 和 Leonard 的连续类(class)获得折扣,而 Sheldon 和 Raj 则没有。

关于mysql - SQL查找连续的季度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7116576/

相关文章:

sql - Microsoft SQL Compact Edition 重命名列

java - 在 Oracle 数据库中调用查询时绑定(bind)后更改参数值

python - 编程错误 : LOB variable no longer valid after subsequent fetch

php - 优化 MySQL 查询以在单个查询中查找用户在不同测试中的排名

mysql - SQL 查询 INNER JOIN 与三个表

php - 如何使用php将打印值存储在mysql表中

php - 输入mysql php后更新

sql - 按月计算的累计值,填补缺失的月份

java - 选择查询很慢

sql - 如何将LONG强制转换为VARCHAR2内联