powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Более элегантное решение
7 сообщений из 7, страница 1 из 1
Более элегантное решение
    #39490968
Adtain
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ПРИМЕР 1: Предлагается следующий набор данных:

Начало действияСотрудникДолжность 01.01.2017 Men 1 Job 101.02.2017Men 1Job 101.03.2017Men 1Job 301.04.2017Men 1Job 401.05.2017Men 1 Job 4
РЕЗУЛЬТАТ: Если один и тот же сотрудник меняет подряд должность, то его необходимо сгруппировать, взял самую первую дату начала и самую последнюю должность:

Начало действияСотрудникДолжность01.01.2017Men 1Job 4
ПРИМЕР 2: Соответственно, если имеем в одной таблице несколько разных сотрудников:

Начало действияСотрудникДолжность 01.01.2017 Men 1 Job 1 01.02.2017 Men 2 Job 101.03.2017Men 2Job 301.04.2017Men 2 Job 4 01.05.2017 Men 1 Job 4
РЕЗУЛЬТАТ: То группировка должна учитывать только непрерывные интервалы работы сотрудников:

Начало действияСотрудникДолжность01.01.2017Men 1Job 101.02.2017Men 2Job 401.05.2017Men 1Job 4
Предлагаемое мною решение на первый взгляд кажется громоздким, хочется упросить:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
with tst as ( select to_date('01.01.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 1' job from dual union all
              select to_date('01.02.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual union all
              select to_date('01.04.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 3' job from dual union all
              select to_date('01.05.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 4' job from dual union all
              select to_date('01.06.2017', 'dd.mm.yyyy') dat, 'Men 2' fio, 'Job 1' job from dual union all
              select to_date('01.07.2017', 'dd.mm.yyyy') dat, 'Men 2' fio, 'Job 1' job from dual union all
              select to_date('01.08.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual union all
              select to_date('01.09.2017', 'dd.mm.yyyy') dat, 'Men 3' fio, 'Job 1' job from dual union all
              select to_date('01.10.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 4' job from dual union all
              select to_date('01.11.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 1' job from dual union all
              select to_date('01.11.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual)

select max(decode(t.gr1, 1, t.dat)) dat,
       t.fio,
       max(decode(t.gr2, 1, t.job)) job
  from (select t.*,
               sum(t.gr1) over(order by t.dat rows between unbounded preceding and current row) gr
          from (select t.dat,
                       t.fio,
                       t.job,
                       decode(t.fio, lag(t.fio)  over(order by t.dat), null, 1) gr1,
                       decode(t.fio, lead(t.fio) over(order by t.dat), null, 1) gr2
                  from tst t) t) t
 group by t.gr, t.fio
...
Рейтинг: 0 / 0
Более элегантное решение
    #39490972
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Adtain
Код: plsql
1.
max(decode(t.gr1, 1, t.dat)) dat,

Просто minAdtain
Код: plsql
1.
max(decode(t.gr2, 1, t.job)) job

Просто first/lastAdtain
Код: plsql
1.
over(order by t.dat rows between unbounded preceding and current row)

Не обязательно.
...
Рейтинг: 0 / 0
Более элегантное решение
    #39490973
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Adtain
Код: plsql
1.
group by t.gr, t.fio

Не нужно
...
Рейтинг: 0 / 0
Более элегантное решение
    #39491015
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Adtain,

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
with tst as ( select to_date('01.01.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 1' job from dual union all
              select to_date('01.02.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual union all
              select to_date('01.04.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 3' job from dual union all
              select to_date('01.05.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 4' job from dual union all
              select to_date('01.06.2017', 'dd.mm.yyyy') dat, 'Men 2' fio, 'Job 1' job from dual union all
              select to_date('01.07.2017', 'dd.mm.yyyy') dat, 'Men 2' fio, 'Job 1' job from dual union all
              select to_date('01.08.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual union all
              select to_date('01.09.2017', 'dd.mm.yyyy') dat, 'Men 3' fio, 'Job 1' job from dual union all
              select to_date('01.10.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 4' job from dual union all
              select to_date('01.11.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 1' job from dual union all
              select to_date('01.11.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual)
select min(dat) dat, fio,
max(job) keep (dense_rank last order by dat) job
from
   (select dat, fio, job,
    row_number() over (partition by fio order by dat) rn_men,
    row_number() over (                 order by dat) rn
    from tst
   )
group by rn - rn_men, fio
order by 1,2,3;

DAT        FIO   JOB
---------- ----- -----
2017-01-01 Men 1 Job 4
2017-06-01 Men 2 Job 1
2017-08-01 Men 1 Job 2
2017-09-01 Men 3 Job 1
2017-10-01 Men 1 Job 2
...
Рейтинг: 0 / 0
Более элегантное решение
    #39491036
Фотография AmKad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уменьшим количество сортировок в плане и выкинем группировку.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
select dat, fio, fv_job as job
from
   (select t.*,
    first_value(decode(ls_last, 1, job) ignore nulls) over (order by dat rows between current row and unbounded following) fv_job
    from
       (select tst.*,
        decode(fio, lag (fio) over (order by dat), 0, 1) is_first,
        decode(fio, lead(fio) over (order by dat), 0, 1) ls_last
        from tst
       ) t
   )t
where is_first = 1;

DAT        FIO   JOB
---------- ----- -----
2017-01-01 Men 1 Job 4
2017-06-01 Men 2 Job 1
2017-08-01 Men 1 Job 2
2017-09-01 Men 3 Job 1
2017-10-01 Men 1 Job 2
...
Рейтинг: 0 / 0
Более элегантное решение
    #39491060
Adtain
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elic,
AmKad,

Спасибо большое за решения!
...
Рейтинг: 0 / 0
Более элегантное решение
    #39491127
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
> with tst as ( select to_date('01.01.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 1' job from dual union all
              select to_date('01.02.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual union all
              select to_date('01.04.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 3' job from dual union all
              select to_date('01.05.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 4' job from dual union all
              select to_date('01.06.2017', 'dd.mm.yyyy') dat, 'Men 2' fio, 'Job 1' job from dual union all
              select to_date('01.07.2017', 'dd.mm.yyyy') dat, 'Men 2' fio, 'Job 1' job from dual union all
              select to_date('01.08.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual union all
              select to_date('01.09.2017', 'dd.mm.yyyy') dat, 'Men 3' fio, 'Job 1' job from dual union all
              select to_date('01.10.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 4' job from dual union all
              select to_date('01.11.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 1' job from dual union all
              select to_date('01.11.2017', 'dd.mm.yyyy') dat, 'Men 1' fio, 'Job 2' job from dual)
-----------------------------------------
select * from tst
match_recognize(
  order by dat
  measures strt.dat as dat
         , strt.fio as fio
         , last(job) as job
  one row per match
  pattern(strt men*)
  define
    men as men.fio = prev(men.fio)
) t

DAT        FIO   JOB 
---------- ----- -----
2017-01-01 Men 1 Job 4 
2017-06-01 Men 2 Job 1 
2017-08-01 Men 1 Job 2 
2017-09-01 Men 3 Job 1 
2017-10-01 Men 1 Job 2 
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Более элегантное решение
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]