我有如下数据。在这里,我需要找到其中几个月的差异应该是> = 6的行。逻辑应该是,我们需要从第一行比较直到我们得到的行,其中diff在几个月是6,然后需要遵循相同的来自新匹配行的逻辑继续运行。
我在下面添加了我的示例数据和预期输出。
Fromdate LectureiD StudentID Diff Months Expected
1-Oct-13 1102 55586 null
15-Oct-13 1102 55586 0
15-Oct-13 1102 55586 0
4-Apr-14 1102 55586 6
19-Dec-14 1102 55586 8
27-Dec-14 1102 55586 0
14-Jan-15 1102 55586 0
14-Jan-15 1102 55586 0
29-Sep-15 1102 55586 8
1-Oct-13 1102 55557 null
15-Oct-13 1102 55557 0
15-Oct-13 1102 55557 0
4-Apr-14 1102 55557 6
19-Dec-14 1102 55557 8
以下是我在oracle中使用分析函数尝试的逻辑。
select lectureid,
studentid,
floor(months_between(fromdate,
lag(fromdate) over (partition by
lectureid,
studentid
order by fromdate
)
)
) monthdiff
from above_table;
由于滞后函数的默认偏移量为1,它只是在此之前检查行,因为我上面提到的逻辑在这里工作不正常,因为需要根据新的动态检查它们之前的行。匹配的行。所以o / p到达这里如下。
用星号突出显示的行因此而出错,因为它仅与其前一行进行比较。
Fromdate LectureiD StudentID Diff Month
1-Oct-13 1102 55586 null
15-Oct-13 1102 55586 0
15-Oct-13 1102 55586 0
*4-Apr-14 1102 55586 5*
19-Dec-14 1102 55586 8
27-Dec-14 1102 55586 0
14-Jan-15 1102 55586 0
14-Jan-15 1102 55586 0
29-Sep-15 1102 55586 8
1-Oct-13 1102 55557 null
15-Oct-13 1102 55557 0
15-Oct-13 1102 55557 0
*4-Apr-14 1102 55557 5*
19-Dec-14 1102 55557 8
非常感谢任何帮助!!!
答案 0 :(得分:2)
递归解决方案:
with tmp as (
select fromdate fd, lectureid lid, studentid sid, null mb,
row_number() over (partition by lectureid, studentid order by fromdate) rn
from above_table ),
cte (fd, ld, lid, sid, mb, rn) as (
select fd, fd, lid, sid, mb, rn from tmp where rn=1
union all
select tmp.fd, case when floor(months_between(tmp.fd, cte.ld)) >= 6
then tmp.fd else cte.ld end,
tmp.lid, tmp.sid, floor(months_between(tmp.fd, cte.ld)), tmp.rn
from tmp join cte on tmp.lid = cte.lid and tmp.sid = cte.sid and tmp.rn = cte.rn+1)
select to_char(fd, 'yyyy-mm-dd') fromdate, lid lecture, sid student, mb
from cte order by sid desc, fd
测试数据和输出:
create table above_table (Fromdate date, LectureiD number(6), StudentID number(6), Diff number(4));
insert into above_table values (date '2013-10-01', 1102, 55586, null);
insert into above_table values (date '2013-10-15', 1102, 55586, 0);
insert into above_table values (date '2013-10-15', 1102, 55586, 0);
insert into above_table values (date '2014-04-04', 1102, 55586, 6);
insert into above_table values (date '2014-12-19', 1102, 55586, 8);
insert into above_table values (date '2014-12-27', 1102, 55586, 0);
insert into above_table values (date '2015-01-14', 1102, 55586, 0);
insert into above_table values (date '2015-01-14', 1102, 55586, 0);
insert into above_table values (date '2015-09-29', 1102, 55586, 8);
insert into above_table values (date '2013-10-01', 1102, 55557, null);
insert into above_table values (date '2013-10-15', 1102, 55557, 0);
insert into above_table values (date '2013-10-15', 1102, 55557, 0);
insert into above_table values (date '2013-10-29', 1102, 55557, 0);
insert into above_table values (date '2014-04-04', 1102, 55557, 6);
insert into above_table values (date '2014-12-19', 1102, 55557, 8);
FROMDATE LECTURE STUDENT MB
---------- ---------- ---------- ----------
2013-10-01 1102 55586
2013-10-15 1102 55586 0
2013-10-15 1102 55586 0
2014-04-04 1102 55586 6
2014-12-19 1102 55586 8
2014-12-27 1102 55586 0
2015-01-14 1102 55586 0
2015-01-14 1102 55586 0
2015-09-29 1102 55586 9
2013-10-01 1102 55557
2013-10-15 1102 55557 0
2013-10-15 1102 55557 0
2013-10-29 1102 55557 0
2014-04-04 1102 55557 6
2014-12-19 1102 55557 8
说明:
子查询tmp
仅为每个讲座和学生分别枚举行:
选择fromdate fd,讲话盖子,studentid sid,null mb, row_number()结束(按课程划分,学生按订单生成)rn
这一行是"锚"递归子查询CTE
,其中我们在第一步中将两行编号为1
从tmp中选择fd,fd,lid,sid,mb,rn,其中rn = 1
在这一步中,我附加了"递归成员"使用条件tmp.rn = cte.rn+1
特别重要的是下面的部分,在这里我要检查最后一次记住的日期和当前行的日期之间是否有六个月:
楼层的情况(months_between(tmp.fd,cte.ld))> = 6然后tmp.fd else cte.ld end
最后select
是语法的一部分。
一些有用的链接: