powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Дни отпуска
25 сообщений из 156, страница 3 из 7
Дни отпуска
    #39449154
123йй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94так что понедельник начинается с 15 числа, а заканчивается 21
а вторник начинается с 22 по ....?
...
Рейтинг: 0 / 0
Дни отпуска
    #39449155
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94stax..,

Тьфу то есть

Ну мы выходные в рассчёт не берем, так что понедельник начинается с 15 числа, а заканчивается 21. То же самое с отпуском, то есть начало - это первое число недели, последнее - конец. Я даже ума не приложу как это реализовать.
я б загнав 53 N в масив, а там уже что угодно
можно конечно и ф-цию менять, но то к ххl


ps
не надо боятся влоб перечислять 53поля таблицы, в етом нет никакого крамола
......
stax
...
Рейтинг: 0 / 0
Дни отпуска
    #39449163
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
123ййNorman94так что понедельник начинается с 15 числа, а заканчивается 21.
Код: plsql
1.
2.
3.
4.
5.
select level week
      ,trunc(trunc(sysdate, 'yyyy'), 'iw') + level * 7 rus_mon
      ,trunc(sysdate, 'yyyy') + level * 7 rus_sun
from   dual
connect by level < 53



Ого, интересно. Но получится ли это совместить с этой строкой?
Код: sql
1.
2.
3.
4.
greatest(
                   trunc (to_date(god, 'yyyy')+(cast(LTRIM(weeks,'N')as number)-1)*7 -6, 'iw')
                 ,to_date(god||'0101', 'yyyymmdd'))
             ,'dd mon')


(взято из контекста функции выше)
...
Рейтинг: 0 / 0
Дни отпуска
    #39449168
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
stax..,

В этом вся беда - динамика - главное требование. Я бы и сам не заморачивался со всем этим.
...
Рейтинг: 0 / 0
Дни отпуска
    #39449170
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
123ййNorman94так что понедельник начинается с 15 числа, а заканчивается 21.
Код: plsql
1.
2.
3.
4.
5.
select level week
      ,trunc(trunc(sysdate, 'yyyy'), 'iw') + level * 7 rus_mon
      ,trunc(sysdate, 'yyyy') + level * 7 rus_sun
from   dual
connect by level < 53


iw week of year (1-52 or 1-53 ) based on the ISO standard.

.....
stax
...
Рейтинг: 0 / 0
Дни отпуска
    #39449177
123йй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stax..,
может предложишь за него все сделать ?
с учетом
автор В этой таблице есть столбцы год, код сотрудника и 52 столбца
...
Рейтинг: 0 / 0
Дни отпуска
    #39449181
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В общем попытался изменить изменение названия столбца в даты в соответствии с тем, что кинули выше

Код: plsql
1.
2.
3.
4.
5.
select God, Kod_sotr, /*weeks*/to_char(
                greatest(
                   (trunc (to_date(god, 'yyyy')+(cast(LTRIM(weeks,'N')as number)-1)*7 -6, 'iw'), trunc (to_date(god, 'yyyy')+(cast(LTRIM(weeks,'N')as number)-1)*7)
                 ,to_date(god||'0101', 'yyyymmdd'))
             ,'dd mon') Weeks_D,



Но ошибка в missing right parameters
...
Рейтинг: 0 / 0
Дни отпуска
    #39449183
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94,

А напомни, откуда взялось требование про динамику в задаче со статичными условиями?
...
Рейтинг: 0 / 0
Дни отпуска
    #39449186
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94stax..,

В этом вся беда - динамика - главное требование. Я бы и сам не заморачивался со всем этим.
можно ж и
EXECUTE IMMEDIATE 'declare ... begin ... end;'

ps
если чесно странные у Вас требования, и главное Вы упорно игнорируете что в году 53 недели

.....
stax
...
Рейтинг: 0 / 0
Дни отпуска
    #39449188
123йй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Дни отпуска
    #39449189
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
stax..Norman94stax..,

В этом вся беда - динамика - главное требование. Я бы и сам не заморачивался со всем этим.
можно ж и
EXECUTE IMMEDIATE 'declare ... begin ... end;'

ps
если чесно странные у Вас требования, и главное Вы упорно игнорируете что в году 53 недели

.....
stax

А пример можно?

Да я не игнорю, я просто забываю об этом) Да, 53 недели)
...
Рейтинг: 0 / 0
Дни отпуска
    #39449198
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не получается даже с таким шаманством

Код: sql
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.
32.
33.
34.
35.
36.
37.
create or replace FUNCTION
 week_fun300(i_code IN INTEGER, i_year in integer)
RETURN VARCHAR2 IS
l_list VARCHAR2(32767);
 l_res VARCHAR2(4000);
 BEGIN SELECT listagg(column_name,',') WITHIN GROUP(ORDER BY to_char(
                greatest(
                   trunc (to_date(i_year||'0101', 'yyyymmdd')+((LTRIM(column_name,'N'))-1)*7, 'iw')
                 ,to_date(i_year||'0101', 'yyyymmdd'))
             ,'dd mon'))
 INTO l_list
 FROM user_tab_columns
 WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
   l_list:='with t2 as(
  select God, Kod_sotr,'||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year)'||
  q'~
 select /* God, Kod_sotr, */ listagg(lag_WN) within group (order by RN,Kod_sotr) vacation
  from (
  select rownum RN, God, Kod_sotr,
  case when lead(Week_Number) over(PARTITION by God order by Kod_sotr) - Week_number > 1 then /*Weeks*/Weeks_D||';'
      when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then            /*Weeks*/Weeks_D||';'
       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then            /*Weeks*/Weeks_D||','
       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then  /*Weeks*/Weeks_D||','
       else null end lag_WN
          from (
                   select God, Kod_sotr, /*weeks*/[color=red]to_char(
                greatest(
                   trunc (to_date(god||'0101', 'yyyymmdd')+(cast(LTRIM(weeks,'N'))-1)*7, 'iw'), trunc (to_date(god, 'yyyy')+(cast(LTRIM(weeks,'N')as number)-1)*7)
                 ,to_date(god||'0101', 'yyyymmdd') Weeks_D, [/color]
                   Vacation, cast(ltrim(weeks,'N')as number) Week_Number from t2
                  unpivot (vacation for weeks in (~'||l_list||q'~))
                 order by God, Kod_sotr, cast(ltrim(weeks,'N')as number)
                )where vacation='о'
          )group by god, Kod_sotr~';
   EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
  RETURN RTRIM(l_res);
  END;




Missing keyword :(
...
Рейтинг: 0 / 0
Дни отпуска
    #39449226
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94stax..пропущено...

можно ж и
EXECUTE IMMEDIATE 'declare ... begin ... end;'

ps
если чесно странные у Вас требования, и главное Вы упорно игнорируете что в году 53 недели

.....
stax

А пример можно?

Да я не игнорю, я просто забываю об этом) Да, 53 недели)

Вам простенький селект (один из 5000 на непрывные интервалы)
добавте любимую Вами динамику

Код: 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.
32.
with u as ( --разворачиаем недели вертикально
select * from grafik unpivot (vacation for weeks in (
--сгенеріть із user_tables
n1 as '01',n2 as '02',n3 as'03',n4 as '04',n5 as '05',n6 as '06',n7 as '07',n8 as '08',n9 as '09',n10 as '10'
))
where god=2017 and kod_sotr=202
)
,w as ( --номеруем для поиска непрырывных
 select 
   u.*
  ,trunc (to_date(god||'0101', 'yyyymmdd') + (weeks-1)*7, 'ww') d
  ,row_number() over (order by weeks) rn
 from u 
 where vacation='o')
--склеиваем результат в строку
select listagg(min(d)||':'||(max(d)+5),'; ') within group (order by min(d)) res
from w
group by god,kod_sotr,d-rn*7
/
SQL> /

RES
--------------------------------------------------------------------------------
15.01.17:27.01.17; 05.02.17:10.02.17; 19.02.17:10.03.17

SQL> select * from grafik;

       GOD   KOD_SOTR N N N N N N N N N N
---------- ---------- - - - - - - - - - -
      2017        222 у   o o у o у o   o
      2017        202   у o o у o у o o o
      2017        111 o   у у у   у   o



зы
если не получится, я добавлю EXECUTE IMMEDIATE

......
stax
...
Рейтинг: 0 / 0
Дни отпуска
    #39449231
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У меня не получается совместить ваш метод с динамикой.

То есть я не могу понять куда подставлять LISTAGG WITHIN GROUP и т.д.

Я с этой пытаюсь совместить

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
create or replace FUNCTION get_week_list3(i_code IN INTEGER, i_year in integer) RETURN VARCHAR2 IS
  l_list  VARCHAR2(32767);
  l_res   VARCHAR2(4000);
BEGIN
SELECT listagg('CASE WHEN '||column_name||' IN(''у'') THEN '||''''|| to_char( trunc (to_date(i_year||'0101', 'yyyymmdd') 
+ ((LTRIM(column_name,'N'))-1)*7, 'ww'), 'dd mon')||''''|| '||''; '' ELSE NULL END ' ,'||') 
WITHIN GROUP(ORDER BY 1)
  INTO  l_list
  FROM  user_tab_columns
  WHERE TABLE_NAME = 'GRAFIK' 
  AND column_name LIKE 'N%';
EXECUTE IMMEDIATE 'SELECT '||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year' INTO l_res USING i_code,i_year;
RETURN RTRIM(l_res);
END;
...
Рейтинг: 0 / 0
Дни отпуска
    #39449236
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94,
счас сделаю
дайте токо строк, будет Вам и белка и свисток

.....
stax
...
Рейтинг: 0 / 0
Дни отпуска
    #39449241
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
stax..,

Cтойте, я ошибся, нужно с этой совместить

Код: sql
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.
32.
33.
34.
35.
36.
37.
38.
create or replace FUNCTION
 week_fun200(i_code IN INTEGER, i_year in integer)
RETURN VARCHAR2 IS
l_list VARCHAR2(32767);
 l_res VARCHAR2(4000);
 BEGIN SELECT listagg(column_name,',') WITHIN GROUP(ORDER BY to_char(
                greatest(
                   trunc (to_date(i_year||'0101', 'yyyymmdd')+((LTRIM(column_name,'N'))-1)*7, 'iw')
                 ,to_date(i_year||'0101', 'yyyymmdd'))
             ,'dd mon'))
 INTO l_list
 FROM user_tab_columns
 WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
   l_list:='with t2 as(
  select God, Kod_sotr,'||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year)'||
  q'~
 select /* God, Kod_sotr, */ listagg(lag_WN) within group (order by RN,Kod_sotr) vacation
  from (
  select rownum RN, God, Kod_sotr,
  case when lead(Week_Number) over(PARTITION by God order by Kod_sotr) - Week_number > 1 then /*Weeks*/Weeks_D||';'
      when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then            /*Weeks*/Weeks_D||';'
       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then            /*Weeks*/Weeks_D||','
       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then  /*Weeks*/Weeks_D||','
       else null end lag_WN
          from (
                   select God, Kod_sotr, /*weeks*/to_char(
                greatest(
                   trunc (to_date(god, 'yyyy')+(cast(LTRIM(weeks,'N')as number)-1)*7 -6, 'iw')
                 ,to_date(god||'0101', 'yyyymmdd'))
             ,'dd mon') Weeks_D, 
                   Vacation, cast(ltrim(weeks,'N')as number) Week_Number from t2
                  unpivot (vacation for weeks in (~'||l_list||q'~))
                 order by God, Kod_sotr, cast(ltrim(weeks,'N')as number)
                )where vacation='о'
          )group by god, Kod_sotr~';
   EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
  RETURN RTRIM(l_res);
  END;


Строки строки...
...
Рейтинг: 0 / 0
Дни отпуска
    #39449269
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94,

Вот тебе твой селект, жаль сам не за хотел разобраться как он работает
Код: 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.
with t2 as(
select '2017' god, '1' kod_sort, 'o' N1, null N2, 'o' N3, 'o' N4, null N5, null N6, 'o' N7, 'o' N8, 'o' N9, 'o' N10, null N11 from dual union all
select '2017' god, '2' kod_sort, null N1, 'o' N2, 'o' N3, 'o' N4, null N5, 'o' N6, 'o' N7, 'o' N8, 'o' N9, 'o' N10, null N11 from dual union all
select '2017' god, '3' kod_sort, 'o' N1, 'o' N2, 'o' N3, 'o' N4, null N5, null N6, 'o' N7, 'o' N8, 'o' N9, null N10, null N11 from dual union all
select '2017' god, '4' kod_sort, 'o' N1, null N2, 'o' N3, 'o' N4, null N5, null N6, 'o' N7, 'o' N8, 'o' N9, 'o' N10, 'o' N11 from dual)

select  Kod_Sort, listagg(lag_WN) within group (order by RN,kod_sort) vacation 
from (
select rownum RN, Kod_Sort,Week_Number,vacation,

case when ((lead(Week_Number,1,100) over(PARTITION by Kod_Sort order by Kod_Sort)- Week_number )>1) and 
          ((Week_number - lag(Week_Number,1,-1) over(PARTITION by Kod_Sort order by Kod_Sort)) > 1 )  then Begin_Week||'-'||End_week||'; '
          
     when lead(Week_Number,1,100) over(PARTITION by Kod_Sort order by Kod_Sort) - Week_number > 1 then End_week||'; '
     when Week_number - lag(Week_Number,1,-1) over(PARTITION by Kod_Sort order by Kod_Sort) > 1 then Begin_Week||'-'
     else null end lag_WN
         from (
                select Kod_Sort, Vacation, to_number(ltrim(weeks,'N')) Week_Number,
                to_char(trunc(to_date(god,'yyyy'),'y')+(to_number(ltrim(weeks,'N'))-1)*7,'dd mon') Begin_Week,
                to_char(trunc(to_date(god,'yyyy'),'y')+(to_number(ltrim(weeks,'N'))-1)*7+6,'dd mon') End_week
                from t2
                unpivot (vacation for weeks in (N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11))
                order by Kod_Sort, to_number(ltrim(weeks,'N'))
              )where vacation='о'
order by Kod_Sort, Week_Number
)
group by Kod_Sort



Kod_Sort vacation

1 01 jan-07 jan; 15 jan-28 jan; 12 feb-11 mar;
2 08 jan-28 jan; 05 feb-11 mar;
3 01 jan-28 jan; 12 feb-04 mar;
4 01 jan-07 jan; 15 jan-28 jan; 12 feb-18 mar;


Теперь САМ переведи его в динамику и пользуй
но лучше разберись КАК он работает
...
Рейтинг: 0 / 0
Дни отпуска
    #39449280
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXL,

Спасибо большое!

Я перевёл в динамический, но теперь он пишет missing expresion

Подскажите, где я ошибся?

Код: sql
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.
32.
33.
34.
35.
36.
37.
38.
39.
create or replace FUNCTION
 week_fun300(i_code IN INTEGER, i_year in integer)
RETURN VARCHAR2 IS
l_list VARCHAR2(32767);
 l_res VARCHAR2(4000);
 BEGIN SELECT listagg(column_name,',') WITHIN GROUP(ORDER BY to_char(
                greatest(
                   trunc (to_date(i_year||'0101', 'yyyymmdd')+((LTRIM(column_name,'N'))-1)*7, 'iw')
                 ,to_date(i_year||'0101', 'yyyymmdd'))
             ,'dd mon'))
 INTO l_list
 FROM user_tab_columns
 WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
   l_list:='with t2 as(
  select God, Kod_sotr,'||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year)'||
  q'~
  select /* God, Kod_sotr, */, listagg(lag_WN) within group (order by RN,kod_sort) vacation 
from (
select rownum RN, Kod_Sort,Week_Number,vacation,
case when ((lead(Week_Number,1,100) over(PARTITION by Kod_Sort order by Kod_Sort)- Week_number )>1) and 
          ((Week_number - lag(Week_Number,1,-1) over(PARTITION by Kod_Sort order by Kod_Sort)) > 1 )  then Begin_Week||'-'||End_week||'; '
          
     when lead(Week_Number,1,100) over(PARTITION by Kod_Sort order by Kod_Sort) - Week_number > 1 then End_week||'; '
     when Week_number - lag(Week_Number,1,-1) over(PARTITION by Kod_Sort order by Kod_Sort) > 1 then Begin_Week||'-'
     else null end lag_WN
         from (
                select Kod_Sort, Vacation, to_number(ltrim(weeks,'N')) Week_Number,
                to_char(trunc(to_date(god,'yyyy'),'y')+(to_number(ltrim(weeks,'N'))-1)*7,'dd mon') Begin_Week,
                to_char(trunc(to_date(god,'yyyy'),'y')+(to_number(ltrim(weeks,'N'))-1)*7+6,'dd mon') End_week
                from t2
                unpivot (vacation for weeks in (~'||l_list||q'~))
                order by Kod_Sort, to_number(ltrim(weeks,'N'))
              )where vacation='о'
order by Kod_Sort, Week_Number
)
group by Kod_Sort~';
   EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
  RETURN RTRIM(l_res);
  END;
...
Рейтинг: 0 / 0
Дни отпуска
    #39449284
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94stax..,

Cтойте, я ошибся, нужно с этой совместить

Код: sql
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.
32.
33.
34.
35.
36.
37.
38.
create or replace FUNCTION
 week_fun200(i_code IN INTEGER, i_year in integer)
RETURN VARCHAR2 IS
l_list VARCHAR2(32767);
 l_res VARCHAR2(4000);
 BEGIN SELECT listagg(column_name,',') WITHIN GROUP(ORDER BY to_char(
                greatest(
                   trunc (to_date(i_year||'0101', 'yyyymmdd')+((LTRIM(column_name,'N'))-1)*7, 'iw')
                 ,to_date(i_year||'0101', 'yyyymmdd'))
             ,'dd mon'))
 INTO l_list
 FROM user_tab_columns
 WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
   l_list:='with t2 as(
  select God, Kod_sotr,'||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year)'||
  q'~
 select /* God, Kod_sotr, */ listagg(lag_WN) within group (order by RN,Kod_sotr) vacation
  from (
  select rownum RN, God, Kod_sotr,
  case when lead(Week_Number) over(PARTITION by God order by Kod_sotr) - Week_number > 1 then /*Weeks*/Weeks_D||';'
      when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then            /*Weeks*/Weeks_D||';'
       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then            /*Weeks*/Weeks_D||','
       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then  /*Weeks*/Weeks_D||','
       else null end lag_WN
          from (
                   select God, Kod_sotr, /*weeks*/to_char(
                greatest(
                   trunc (to_date(god, 'yyyy')+(cast(LTRIM(weeks,'N')as number)-1)*7 -6, 'iw')
                 ,to_date(god||'0101', 'yyyymmdd'))
             ,'dd mon') Weeks_D, 
                   Vacation, cast(ltrim(weeks,'N')as number) Week_Number from t2
                  unpivot (vacation for weeks in (~'||l_list||q'~))
                 order by God, Kod_sotr, cast(ltrim(weeks,'N')as number)
                )where vacation='о'
          )group by god, Kod_sotr~';
   EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
  RETURN RTRIM(l_res);
  END;


Строки строки...

в чем разница? почему минус 6 (*7 -6)?

Код: 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.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
declare
 function f ( p_god number,p_kod_sotr number, p_vacation varchar2 :='o')
 return varchar2
is
 l_res varchar2(4000);
 l_list VARCHAR2(32767);
begin
 SELECT listagg(column_name||' as '''||lpad(ltrim(column_name,'N'),2,'0')||'''',',') WITHIN GROUP(ORDER BY null)
 INTO l_list
 FROM user_tab_columns
 WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
l_list:=q'[
with u as ( --разворачиаем недели вертикально
select * from grafik unpivot (vacation for weeks in (
--сгенеріть із user_tables
]'||l_list||
q'[
))
where god=:g and kod_sotr=:s
)
,w as ( --номеруем для поиска непрырывных
 select
   u.*
--  ,trunc (to_date(god||'0101', 'yyyymmdd') + (weeks-1)*7, 'ww') d
    ,greatest(
     trunc (to_date(god||'0101', 'yyyymmdd')+(weeks-1)*7, 'iw')
     ,to_date(god||'0101', 'yyyymmdd')) d
  ,row_number() over (order by weeks) rn
 from u
 where vacation=:o)
--склеиваем результат в строку
select 
 listagg(to_char(min(d),'dd Mon')||':'||
     to_char(least(add_months(trunc(min(d),'y'),12)-1,max(d)+5),'dd Mon'),'; ') 
 within group (order by min(d)) res
from w
group by god,kod_sotr,d-rn*7
]';
 EXECUTE IMMEDIATE l_list INTO l_res USING p_god,p_kod_sotr,p_vacation;
 return l_res;
end;
begin
 dbms_output.put_line(f(2017,202));
end;
/
SQL> /
09 Січ:21 Січ; 30 Січ:04 Лют; 13 Лют:04 Бер; 18 Гру:30 Гру

SQL> select * from GRAFIK;

       GOD   KOD_SOTR N N N N N N N N N N N N
---------- ---------- - - - - - - - - - - - -
      2017        222 у   o o у o у o   o
      2017        202   у o o у o у o o o o o
      2017        111 o   у у у   у   o

SQL> desc GRAFIK;
 Name
 ------------------------------------------------
 GOD
 KOD_SOTR
 N1
 N2
 N3
 N4
 N5
 N6
 N7
 N8
 N9
 N10
 N52
 N53
...
Рейтинг: 0 / 0
Дни отпуска
    #39449285
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94MaximaXXL,

Спасибо большое!

Я перевёл в динамический, но теперь он пишет missing expresion

Подскажите, где я ошибся?

Код: sql
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.
32.
33.
34.
35.
36.
37.
38.
39.
create or replace FUNCTION
 week_fun300(i_code IN INTEGER, i_year in integer)
RETURN VARCHAR2 IS
l_list VARCHAR2(32767);
 l_res VARCHAR2(4000);
 BEGIN SELECT listagg(column_name,',') WITHIN GROUP(ORDER BY to_char(
                greatest(
                   trunc (to_date(i_year||'0101', 'yyyymmdd')+((LTRIM(column_name,'N'))-1)*7, 'iw')
                 ,to_date(i_year||'0101', 'yyyymmdd'))
             ,'dd mon'))
 INTO l_list
 FROM user_tab_columns
 WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
   l_list:='with t2 as(
  select God, Kod_sotr,'||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year)'||
  q'~
  select /* God, Kod_sotr, */, listagg(lag_WN) within group (order by RN,kod_sort) vacation 
from (
select rownum RN, Kod_Sort,Week_Number,vacation,
case when ((lead(Week_Number,1,100) over(PARTITION by Kod_Sort order by Kod_Sort)- Week_number )>1) and 
          ((Week_number - lag(Week_Number,1,-1) over(PARTITION by Kod_Sort order by Kod_Sort)) > 1 )  then Begin_Week||'-'||End_week||'; '
          
     when lead(Week_Number,1,100) over(PARTITION by Kod_Sort order by Kod_Sort) - Week_number > 1 then End_week||'; '
     when Week_number - lag(Week_Number,1,-1) over(PARTITION by Kod_Sort order by Kod_Sort) > 1 then Begin_Week||'-'
     else null end lag_WN
         from (
                select Kod_Sort, Vacation, to_number(ltrim(weeks,'N')) Week_Number,
                to_char(trunc(to_date(god,'yyyy'),'y')+(to_number(ltrim(weeks,'N'))-1)*7,'dd mon') Begin_Week,
                to_char(trunc(to_date(god,'yyyy'),'y')+(to_number(ltrim(weeks,'N'))-1)*7+6,'dd mon') End_week
                from t2
                unpivot (vacation for weeks in (~'||l_list||q'~))
                order by Kod_Sort, to_number(ltrim(weeks,'N'))
              )where vacation='о'
order by Kod_Sort, Week_Number
)
group by Kod_Sort~';
   EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
  RETURN RTRIM(l_res);
  END;



/* God, Kod_sotr, */, - лишняя запетуха
...
Рейтинг: 0 / 0
Дни отпуска
    #39449294
123йй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stax..with u as ( --разворачиаем недели вертикально
сначала свернем недели а потом развернем их ?
...
Рейтинг: 0 / 0
Дни отпуска
    #39449300
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXL, stax..

Я безмерно благодарен вам. Я поднастроил всё под себя, взяв от одного варианта и другого, теперь всё получилось!

автор почему минус 6 (*7 -6)?

Прикол в том, что он начинал отсчёт не с понедельника, а с воскресенья. Видимо что то с системными датами напутано..
...
Рейтинг: 0 / 0
Дни отпуска
    #39449306
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Norman94,

MaximaXXL

Если не сложно помогите понять эти строки
авторcase when lead(Week_Number) over(PARTITION by God order by Kod_sotr) - Week_number > 1 then /*Weeks*/Weeks_D||';'
when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then /*Weeks*/Weeks_D||';'
when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then /*Weeks*/Weeks_D||','
when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then /*Weeks*/Weeks_D||','
else null end lag_WN


Что здесь происходит?
...
Рейтинг: 0 / 0
Дни отпуска
    #39449311
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
123ййstax..with u as ( --разворачиаем недели вертикально
сначала свернем недели а потом развернем их ?
можна по разному, ето один из вариантов, мне кажется самым простым

.....
stax
...
Рейтинг: 0 / 0
Дни отпуска
    #39449314
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94MaximaXXL, stax..

Я безмерно благодарен вам. Я поднастроил всё под себя, взяв от одного варианта и другого, теперь всё получилось!

автор почему минус 6 (*7 -6)?

Прикол в том, что он начинал отсчёт не с понедельника, а с воскресенья. Видимо что то с системными датами напутано..

ето ЗАГОТОВКА, надо допиливать под себя
напр
конец недели я добавлял 5, но мож надо 4 или 6
наскоко помню первая неделя у вас хитрая (greatest ...), соответственно окончание надо тож доработать

с "приколом -6" надо разобраться, в 2018 и далее все будет хорошо?

и тд

......
stax
...
Рейтинг: 0 / 0
25 сообщений из 156, страница 3 из 7
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Дни отпуска
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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