根据前一行和当前行中的值生成序列

时间:2016-06-05 16:49:14

标签: sql oracle11g

我在下表中有学生信息。

S_ID    Group_ID    Date    Score
12345   1           1/1/2015    1
12345   1           2/1/2015    2
12345   1           3/1/2015    4
12345   1           4/1/2015    5
12345   1           9/1/2015    3
12345   1           10/1/2015   8
12345   2           1/1/2015    2
12345   2           2/1/2015    4
12345   2           3/1/2015    6

我想在添加序列列后为少数学生生成一个新表,如下所示

S_ID    Group_ID    Date       Score    Sequence
12345   1           1/1/2015    1       1
12345   1           2/1/2015    2       2
12345   1           3/1/2015    4       3
12345   1           4/1/2015    5       4
12345   1           9/1/2015    3       3
12345   1          10/1/2015    8       4
12345   2           1/1/2015    2       2
12345   2           2/1/2015    4       3
12345   2           3/1/2015    6       4

规则:

  • 应为S_ID,Group_I
  • 的每个组合生成序列
  • 对于第一条记录,序列号将与分数
  • 相同
  • 第二个记录以后,这将是1 +前一个序列号
  • 如果前一行和当前行的日期之间的差异是 超过100天,序列号将重新启动(与...相同) 该记录的得分)

这是一个大表,我正在寻找最优化的SQL。任何帮助将不胜感激

1 个答案:

答案 0 :(得分:0)

这里的技巧是找到序列号重新开始的位置。这适用于新学生,小组,以及之前的日期差距太大。对于后者,您可以使用lag()来计算"新日期开始标记"然后将其聚合以获得分组。

select t.*,
       (first_value(score) over (partition by s_id, group_id, grp order by date) +
        row_number() over (partition by s_id, group_id, grp order by date) - 1
       ) as sequence
from (select t.*,
             sum(case when prev_date is null or prev_date < date - 100
                      then 1 else 0
                 end) over (partition by s_id, group_id order by date) as grp
      from (select t.*,
                   lag(date) over (partition by s_id, group_id order by date) as prev_date
            from t
           ) t
     ) t;