2015-12-31 2 views
3

У меня есть данные, как показано ниже. В этом мне нужно найти строки, где diff в их месяцах должен быть> = 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 

Ниже приведена логика, которую я попытался использовать аналитическую функцию в оракуле.

select lectureid, 
     studentid, 
     floor(months_between(fromdate, 
          lag(fromdate) over (partition by 
                lectureid, 
                studentid 
               order by fromdate 
               ) 
          ) 
      ) monthdiff 
from above_table; 

Поскольку функция задержки будет по умолчанию смещение 1 он просто проверяет строку только до этого из-за того, что логика я уже говорил выше, не работает должным образом здесь, так что нужно сверяется их предыдущих строк динамически на основе новой согласованной строки. Таким образом, я получаю здесь, как показано ниже.

Строки, выделенные звездочкой, становятся неправильными из-за этого, поскольку они сравниваются только с его непосредственной предшествующей строкой.

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

Я упомянул правильный набор данных выше .. Я только что упомянул последний набор данных, чтобы выделить, где я ошибаюсь ..Thx – arunb2w

+0

Извините, что это было не совсем правильно. Я считаю. Последний столбец не является идентификатором студента, column (diffmonth) – arunb2w

+0

Для этой строки '* 4-Apr-14 1102 55586 5 *' student 1102, что было бы результатом, если бы первая дата была также «15-Oct-13» –

ответ

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 

Пояснение:

  1. подзапросы tmp только перечисляет строку отдельно для каждой лекции и шпилек Энты:

    выберите FromDate Fd, lectureid крышка, studentid с.и.д., нулевые мб, row_number() над (раздел по lectureid, studentid порядка по FromDate) р-н

  2. Эта линия является "якорь" рекурсивного подзапроса CTE, где мы возьмем два ряда с пронумерованными, как 1 на первом этапе

    выберите Fd, Fd, крышки, SID, мБ, р-н от TMP, где гп = 1

  3. в этом шаге я прилагаю «рекурсивная член "с использованием условия tmp.rn = cte.rn+1 Особо importa nt является частью ниже, здесь я проверяю, есть ли шесть месяцев между последней запомненной датой и датой из текущей строки:

    case when floor (months_between (tmp.fd, cte.ld))> = 6 then tmp.fd else cte.ld end

  4. Последнее select обязательна часть синтаксиса.


Некоторые полезные ссылки:

+0

Можно ли сделать то же самое, что и использовать connect. Если это так, вы можете направить меня. – arunb2w

+0

@ arunb2w - По-моему, мы не можем использовать 'connect by' здесь. Рекурсивные запросы дают еще несколько возможностей, которые я использовал для вычисления временного столбца 'ld' и, следовательно, столбца' mb' (между месяцами). Я не понимаю, как это можно сделать в 'connect by'. Недостаточно «Приор». Альтернативой рекурсивному запросу является PLSQL или предложение 'MODEL' (не уверенный в этом). –

+0

У меня есть несколько вопросов по этой теме. не возражайте, разъясняя мне это. Я создал чат-комнату здесь. http://chat.stackoverflow.com/rooms/101205/room-for-arunb2w-and-ponder-stibbons, пожалуйста, присоединяйтесь, если у вас есть свободное время – arunb2w

Смежные вопросы