使用分析/连接函数Oracle标记接下来3天的记录

时间:2014-03-24 03:33:15

标签: sql oracle

对于每个ID,我想标记接下来3天的记录。对于不在3天内的任何记录,它再次从1开始。 我不想使用循环,因为它可能会降低性能。

我的表格如下

Id        Date    Flag 
-------------------------------------------
1       Jan 1st   1 (starting record for id 1. Any record with Jan 2nd - Jan 4th will be set to 0) 
1       Jan 3rd   0 (From Jan 1st, it is within 3 days)
1       Jan 5th   1 (From Jan 1st, it is NOT within 3 days. So flag as 1.
                     Any record with Jan 6th - Jan 8th will be set to 0)
1       Jan 6th   0 (From Jan 5th, it is within 3 days)
2       Jan 15th  1 (Starting record for id 2)
2       Jan 17th  0 (From Jan 15th, it is within 3 days)
2       Jan 19th  1 (From Jan 15th, it is NOT within 3 days. So flag as 1)

1 个答案:

答案 0 :(得分:1)

编辑:这个答案不正确

测试案例1:

with src as (
  select 1 as id, date '2014-01-01' as d, 1 as test from dual
  union all select 1, date '2014-01-03', 0 from dual
  union all select 1, date '2014-01-05', 1 from dual
  union all select 1, date '2014-01-06', 0 from dual
  union all select 2, date '2014-01-15', 1 from dual
  union all select 2, date '2014-01-17', 0 from dual
  union all select 2, date '2014-01-19', 1 from dual)
,q as (
  select src.*
        ,first_value(d)
         over (partition by id
               order by d
               range numtodsinterval(3, 'day') preceding
              ) as d1
  from src)
select q.id, to_char(q.d,'DD/MM/YYYY') as d
      ,case when q.d1 =
         lag(q.d1)
         over (partition by id order by d)
       then 0
       else 1
       end as flag
      ,test
from q
order by id, d;

结果(测试通过):

id  d            flag  test
==  ==========   ====  ====
1   01/01/2014  1     1
1   03/01/2014  0     0
1   05/01/2014  1     1
1   06/01/2014  0     0
2   15/01/2014  1     1
2   17/01/2014  0     0
2   19/01/2014  1     1

测试案例2:

with src as (
  select 1 as id, date '2014-01-12' as d, 1 as test from dual
  union all select 1, date '2014-01-13', 0 from dual
  union all select 1, date '2014-01-15', 0 from dual
  union all select 1, date '2014-01-18', 1 from dual
  union all select 1, date '2014-01-21', 0 from dual
  union all select 1, date '2014-02-02', 1 from dual
  union all select 1, date '2014-02-03', 0 from dual
  union all select 1, date '2014-02-09', 1 from dual
  union all select 1, date '2014-02-10', 0 from dual
  union all select 1, date '2014-02-11', 0 from dual
  union all select 1, date '2014-02-18', 1 from dual
  union all select 1, date '2014-02-21', 0 from dual)
,q as (
  select src.*
        ,first_value(d)
         over (partition by id
               order by d
               range numtodsinterval(3, 'day') preceding
              ) as d1
  from src)
select q.id, to_char(q.d,'DD/MM/YYYY') as d
      ,case when q.d1 =
         lag(q.d1)
         over (partition by id order by d)
       then 0
       else 1
       end as flag
      ,test
from q
order by id, d;

结果(测试失败):

id  d          flag test
==  ========== ==== ====
 1  12/01/2014  1   1
 1  13/01/2014  0   0
 1  15/01/2014  0   0
 1  18/01/2014  1   1
 1  21/01/2014  1   0   <--- test failed
 1  02/02/2014  1   1
 1  03/02/2014  0   0
 1  09/02/2014  1   1
 1  10/02/2014  0   0
 1  11/02/2014  0   0
 1  18/02/2014  1   1
 1  21/02/2014  0   0