powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Поиск по строке
49 сообщений из 49, показаны все 2 страниц
Поиск по строке
    #39421158
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте. Имеется длинная таблица состоящая из 30 столбцов, которые обозначаются неделями (N1, N2, N3 и т.д.)

N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 N13 N14 N15 N16 N17
о о о о о о о о о о

Как видно, в некоторых неделях проставлены обозначения, когда у человека внеочередной отпуск. Собственно, как вывести интервал одной недели мне известно из этой функции

create or replace FUNCTION get_week_list1(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.mm')||'||''; '' 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;

Потом собственно в вызове я делаю запрос который выводит мне 1 и последнюю строку

SELECT t.god, t.kod_sotr, regexp_substr (get_week_list1(t.kod_sotr,t.god), '^([[:digit:]]+)(,)([[:digit:]]+)(;)') as week_first,
regexp_substr (get_week_list1(t.kod_sotr,t.god), '([[:digit:]]+)(,)([[:digit:]]+)(;)$') as week_last FROM GRAFIK t;

Но что делать, если у меня 2 интервала недель? Нужен цикл? Если да, то подскажите как именно мне надо указать что вот там один интервал, а вот там другой?
...
Рейтинг: 0 / 0
Поиск по строке
    #39421159
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Norman94, в шапке неправильно таблица сделана, вот как
...
Рейтинг: 0 / 0
Поиск по строке
    #39421207
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94Здравствуйте. Имеется длинная таблица состоящая из 30 столбцов, которые обозначаются неделями (N1, N2, N3 и т.д.)
Код: plaintext
1.
2.
N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 N13 N14 N15 N16 N17
о  о  о  о  о              о   о   о   о   о
Как видно, в некоторых неделях проставлены обозначения, когда у человека внеочередной отпуск. Собственно, как вывести интервал одной недели мне известно из этой функции
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
create or replace FUNCTION get_week_list1(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.mm')||'||''; '' 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;


Потом собственно в вызове я делаю запрос который выводит мне 1 и последнюю строку
Код: plsql
1.
2.
3.
4.
5.
SELECT t.god
       , t.kod_sotr
       , regexp_substr (get_week_list1(t.kod_sotr,t.god), '^([[:digit:]]+)(,)([[:digit:]]+)(;)') as week_first
       , regexp_substr (get_week_list1(t.kod_sotr,t.god), '([[:digit:]]+)(,)([[:digit:]]+)(;)$') as week_last 
FROM GRAFIK t;


Но что делать, если у меня 2 интервала недель? Нужен цикл? Если да, то подскажите как именно мне надо указать что вот там один интервал, а вот там другой?

Попробуй научиться использовать форматирование кода и сообщений на форуме.

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

Я хочу сделать так, чтобы в ответе у меня получались два интервала отпусков. То есть интервал один и интервал два. Как сделать один интервал я знаю, а вот как сделать так, чтобы было два интервала я не знаю. Я понимаю, что нужен цикл, но не понимаю по какому критерию разделить эти значения, чтобы получилось два интервала.

А если вообще кратко, то мне надо чтобы ответ выводился так:

N1, N5; N10, N13;
...
Рейтинг: 0 / 0
Поиск по строке
    #39421297
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94,

unpivot + stff start of group
...
Рейтинг: 0 / 0
Поиск по строке
    #39421303
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env,

Я хотел так сделать, беда в том, что у меня динамический прогон по столбцам с помощью column_table.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421384
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Возник ещё вопрос. Так как мне остро необходимо использовать динамический прогон, имеется ли возможность привязать UNPIVOT к вызову функции?
...
Рейтинг: 0 / 0
Поиск по строке
    #39421406
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А можно как то указать, если после значения следует пустая ячейка, то она должна быть последней в интервале? Или наоборот, если до неё есть пустые ячейки, то первый? Я сколько не читал про regexp_substr, ничего толкого не нашёл. Может кто что подсказать по поводу этого?
...
Рейтинг: 0 / 0
Поиск по строке
    #39421413
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
SELECT t.god
       , t.kod_sotr
       , regexp_substr (get_week_list1(t.kod_sotr,t.god), '^([[:digit:]]+)(,)([[:digit:]]+)(;)') as week_first
       , regexp_substr (get_week_list1(t.kod_sotr,t.god), '([[:digit:]]+)(,)([[:digit:]]+)(;)$') as week_last 
FROM GRAFIK t;



Norman94 Я хочу сделать так, чтобы в ответе у меня получались два интервала отпусков. То есть интервал один и интервал два. Как сделать один интервал я знаю, а вот как сделать так, чтобы было два интервала я не знаю. Я понимаю, что нужен цикл, но не понимаю по какому критерию разделить эти значения, чтобы получилось два интервала.

А если вообще кратко, то мне надо чтобы ответ выводился так:

N1, N5; N10, N13;

Глянул в хрустальный шар и если твой селект возврыщает похожее то вот:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
with t1 as(
SELECT '1' god, '2' kod_sort, 'N3'  week_first, 'N5'  week_last from dual union all
SELECT '1' god, '2' kod_sort, 'N10' week_first, 'N13' week_last from dual union all
SELECT '2' god, '3' kod_sort, 'N1'  week_first, 'N11' week_last from dual union all
SELECT '2' god, '4' kod_sort, 'N4'  week_first, 'N5'  week_last from dual union all
SELECT '2' god, '2' kod_sort, 'N11' week_first, 'N15' week_last from dual)

select god, listagg(week_first||','||week_last||';') within group (order by kod_sort) vacation from t1
group by god
...
Рейтинг: 0 / 0
Поиск по строке
    #39421414
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94Возник ещё вопрос. Так как мне остро необходимо использовать динамический прогон, имеется ли возможность привязать UNPIVOT к вызову функции?

Чем вызвана такая необходимость? Если есть возможность обойтись без динамического sql - лучше воспользоватся ей.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421417
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXL,

немножко не то. Расскажу ещё раз.

У меня функция динамически пробегает по строке, ищет, если столбец со буквой N имеет значение "о", то он вытаскивает название этого столбца. Этот запрос, что вы привели как цитата с моего поста, она выявляет первое и последнее значение единичного интервала. То есть вместо N1, N2, N3, N4 он выведет N1, N4;

А если у меня недели идут так N1, N2, N3, N4, N8, N9, N10, N11 то он выведет N1, N11, что неправильно, а должно быть N1, N4; N8,N11;
...
Рейтинг: 0 / 0
Поиск по строке
    #39421419
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
envNorman94Возник ещё вопрос. Так как мне остро необходимо использовать динамический прогон, имеется ли возможность привязать UNPIVOT к вызову функции?

Чем вызвана такая необходимость? Если есть возможность обойтись без динамического sql - лучше воспользоватся ей.

Необходимость заключается в том, что столбцов куча, они различаются лишь числовым порядком, и их значение может меняться. К сожалению без динамики нельзя.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421435
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если что, таблица выгдядит таким образом
...
Рейтинг: 0 / 0
Поиск по строке
    #39421490
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.
28.
29.
30.
with t2 as(
select '1' god, '2' kod_sort, 'o' N1, 'o' N2, 'o' N3, 'o' N4, null N5, null N6, 'o' N7, 'o' N8, 'o' N9, 'o' N10, null N11 from dual union all
select '2' 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 '3' god, '2' 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 '4' god, '2' 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)

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

case when lead(Week_Number) over(PARTITION by God order by Kod_Sort) - Week_number > 1 then Weeks||';'
     when lead(Week_Number) over(PARTITION by God order by Kod_Sort) is null then Weeks||';'
     when lag(Week_Number) over(PARTITION by God order by Kod_Sort) is null then Weeks||','
     when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_Sort) > 1 then Weeks||','
     else null end lag_WN

         from (
                select God, Kod_Sort, weeks, Vacation, cast(ltrim(weeks,'N')as number) Week_Number from t2
                unpivot (vacation for weeks in (N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11))
                order by God, Kod_Sort, cast(ltrim(weeks,'N')as number)
              )
     )
group by god, Kod_Sort



1              2              N1,N4;N7,N10;
2              2              N2,N4;N6,N10;
3              2              N1,N4;N7,N9;
4              2              N1;N3,N4;N7,N10;


C
Select можно упростить, но для понимания оставил такой
...
Рейтинг: 0 / 0
Поиск по строке
    #39421502
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXLNorman94,
Код: 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.
with t2 as(
select '1' god, '2' kod_sort, 'o' N1, 'o' N2, 'o' N3, 'o' N4, null N5, null N6, 'o' N7, 'o' N8, 'o' N9, 'o' N10, null N11 from dual union all
select '2' 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 '3' god, '2' 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 '4' god, '2' 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)

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

case when lead(Week_Number) over(PARTITION by God order by Kod_Sort) - Week_number > 1 then Weeks||';'
     when lead(Week_Number) over(PARTITION by God order by Kod_Sort) is null then Weeks||';'
     when lag(Week_Number) over(PARTITION by God order by Kod_Sort) is null then Weeks||','
     when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_Sort) > 1 then Weeks||','
     else null end lag_WN

         from (
                select God, Kod_Sort, weeks, Vacation, cast(ltrim(weeks,'N')as number) Week_Number from t2
                unpivot (vacation for weeks in (N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11))
                order by God, Kod_Sort, cast(ltrim(weeks,'N')as number)
              )
     )
group by god, Kod_Sort



1              2              N1,N4;N7,N10;
2              2              N2,N4;N6,N10;
3              2              N1,N4;N7,N9;
4              2              N1;N3,N4;N7,N10;


C
Select можно упростить, но для понимания оставил такой

Это динамический подход?
...
Рейтинг: 0 / 0
Поиск по строке
    #39421516
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Функция выше крайне полезная, но скажите пожалуйста, как мне совместить эту функцию и то, что вы кинули выше? Честное слово, у меня никак не получается

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
create or replace FUNCTION week(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.mm')||'||''; '' 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
Поиск по строке
    #39421523
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94,
Вы случайно не Аналитик по профессии?
Вы поставили задачу, я ее решил.

Как совместить что-то с чем-то ... задачи не стояло =)
Да и зачем что-то совмещать, если результат достигнут без оного, я пока не понял.

Расширьте плиз условие и если будет время - я посмотрю.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421528
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXLNorman94,
Вы случайно не Аналитик по профессии?
Вы поставили задачу, я ее решил.

Как совместить что-то с чем-то ... задачи не стояло =)
Да и зачем что-то совмещать, если результат достигнут без оного, я пока не понял.

Расширьте плиз условие и если будет время - я посмотрю.

Извините, я просто забыл указать, что сделать это надо с помощью динамического подхода. Задачу вы решили, причём использовали цикл, что несоменно здорово. Теперь мне нужно это совместить с моей функцией, где проходит динамический прогон по таблице (это обязательная задача). Таблица называется Table. Функция выше она ходит по столбцам, отделяет обычные столбцы от тех, что имеют литру N (они то и запиханы как одна большая динамическая строка). Но функция CASE WHEN там уже лишняя, это я понял. Теперь же я пытаюсь совместить ваше решение с моим, но у меня не выходит, или я что то не понимаю.

Пожалуйста, выручите!

Условия таковы: вбиваю номер сотрудника, год, он выводит интервалы недель где у этого человека отпуск. Всё.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421537
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94Это динамический подход?
это
envunpivot + start of group

В данной задаче нет никакой необходимости в динамических запросах.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421545
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
envВ данной задаче нет никакой необходимости в динамических запросах.
В моём случае к сожалению есть.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421589
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94Извините, я просто забыл указать, что сделать это надо с помощью динамического подхода. Задачу вы решили, причём использовали цикл, что несоменно здорово. Теперь мне нужно это совместить с моей функцией, где проходит динамический прогон по таблице (это обязательная задача). Таблица называется Table. Функция выше она ходит по столбцам, отделяет обычные столбцы от тех, что имеют литру N (они то и запиханы как одна большая динамическая строка). Но функция CASE WHEN там уже лишняя, это я понял. Теперь же я пытаюсь совместить ваше решение с моим, но у меня не выходит, или я что то не понимаю.

Пожалуйста, выручите!

Условия таковы: вбиваю номер сотрудника, год, он выводит интервалы недель где у этого человека отпуск. Всё.

Вот вы ищите на опу приключений.

Возьмите мой селект, замените t2 на GRAFIK, динамически вставьте в него блок N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11... (если не знаете какие поля есть в таблице) и добавьте условие 'WHERE kod_sotr=:A AND god=:year'.
Кстати god я перевел как "Бог" и думал что вы так юзеров назвали, что приведет к замене местами god и kod_sort в моем примере.

Возвращать придется vacation.
Но делать :
Код: plsql
1.
2.
3.
4.
SELECT t.god
       , t.kod_sotr
       , get_week_list1(t.kod_sotr,t.god)
FROM GRAFIK t;


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

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

иначе говоря, тут не решают задачи, а помогают в решении
envunpivot + stff start of group

Должна была Вам помочь более чем

Я написал работающий пример, рассказал что менять в соответствии с Вашими дополнениями

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

Код: sql
1.
2.
3.
4.
SELECT listagg(column_name||(LTRIM(column_name,'N'), ', ')
  FROM  user_tab_columns
  WHERE TABLE_NAME = 'GRAFIK' 
  AND column_name LIKE 'N%';


Он выводит чушь в стиле N0101, N0202
...
Рейтинг: 0 / 0
Поиск по строке
    #39421634
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXLNorman94,

иначе говоря, тут не решают задачи, а помогают в решении
envunpivot + stff start of group

Должна была Вам помочь более чем

Я написал работающий пример, рассказал что менять в соответствии с Вашими дополнениями

Но я не вправе решать что Вам брать и что оставить для решения конкретно Вашей задачи.
Проявите интеллект и подумайте ...

У меня такой глупый вопрос:
unpivot можно использовать с динамическим блоком?
...
Рейтинг: 0 / 0
Поиск по строке
    #39421648
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXLNorman94,

иначе говоря, тут не решают задачи, а помогают в решении
envunpivot + stff start of group

Должна была Вам помочь более чем

Я написал работающий пример, рассказал что менять в соответствии с Вашими дополнениями

Но я не вправе решать что Вам брать и что оставить для решения конкретно Вашей задачи.
Проявите интеллект и подумайте ...

И ещё последний вопрос, ответьте пожалуйста, в какое именно место нужно добавить, чтобы он искал именно те столбцы со значениями "о", потому что неисключено, что в таблице могут быть другие символы, которые в данном случае искать не нужно
...
Рейтинг: 0 / 0
Поиск по строке
    #39421653
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94И ещё, как мне в таком случае сделать динамический общий запрос? Если я введу

Код: sql
1.
2.
3.
4.
SELECT listagg(column_name||(LTRIM(column_name,'N'), ', ')
  FROM  user_tab_columns
  WHERE TABLE_NAME = 'GRAFIK' 
  AND column_name LIKE 'N%';


Он выводит чушь в стиле N0101, N0202

Вы будто накручиваете счетчик сообщений
что вернет column_name||(LTRIM(column_name,'N') если column_name = 'N01'?

Norman94У меня такой глупый вопрос:
unpivot можно использовать с динамическим блоком?


Попробуйте, любой результат Вам будет на пользу ...
...
Рейтинг: 0 / 0
Поиск по строке
    #39421660
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot Norman94]MaximaXXLNorman94,

И ещё последний вопрос, ответьте пожалуйста, в какое именно место нужно добавить, чтобы он искал именно те столбцы со значениями "о", потому что неисключено, что в таблице могут быть другие символы, которые в данном случае искать не нужно

нивкакое
UNPIVOT без приставки INCLUDE NULLS просто выкинет столбцы с пустыми значениями.
А вообще то мой Вам совет читайте доки и больше экспериментируйте и будет Вам счастье.
...
Рейтинг: 0 / 0
Поиск по строке
    #39421676
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXL,

Ладно, спасибо большое!
...
Рейтинг: 0 / 0
Поиск по строке
    #39421815
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94Здравствуйте. Имеется длинная таблица состоящая из 30 столбцов, которые обозначаются неделями (N1, N2, N3 и т.д.)

N1 N2 N3 N4 N5 N6 N7 N8 N9 N10 N11 N12 N13 N14 N15 N16 N17
о о о о о о о о о о

Как видно, в некоторых неделях проставлены обозначения, когда у человека внеочередной отпуск. Собственно, как вывести интервал одной недели мне известно из этой функции

create or replace FUNCTION get_week_list1(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.mm')||'||''; '' 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;

Потом собственно в вызове я делаю запрос который выводит мне 1 и последнюю строку

SELECT t.god, t.kod_sotr, regexp_substr (get_week_list1(t.kod_sotr,t.god), '^([[:digit:]]+)(,)([[:digit:]]+)(;)') as week_first,
regexp_substr (get_week_list1(t.kod_sotr,t.god), '([[:digit:]]+)(,)([[:digit:]]+)(;)$') as week_last FROM GRAFIK t;

Но что делать, если у меня 2 интервала недель? Нужен цикл? Если да, то подскажите как именно мне надо указать что вот там один интервал, а вот там другой?

непонятно
1) почему нужен динамический?
2) странно что 31n, больше похоже на дни (недель в году больше)

сделал влоб (Вам надо перечислить все N)
Код: 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.
with GRAFIK as (
select 111 kod_sotr, 2017 god, '' n1,'o' n2,'o' n3,'-' n4,'o' n5,'o' n6,'' n7,'o' n8,'' n9,'o' n10,'o' n11,/*...*/'o' n30,'o' n31 from dual union all
select 222 kod_sotr, 2018 god, 'o' n1,'o' n2,'o' n3,'o' n4,'S' n5,'t' n6,'a' n7,'s' n8,'o' n9,'o' n10,'o' n11,/*...*/'o' n30,'' n31 from dual union all
select 333 kod_sotr, 2018 god, 'o' n1,'' n2,'o' n3,'o' n4,'o' n5,'o' n6,'o' n7,'o' n8,'o' n9,'o' n10,'o' n11,/*...*/'x' n30,'o' n31 from dual 
)
select 
decode (nvl(n1,'*'),'o','1:','') 
||case decode(n1,'o','o','*')||decode(n2,'o','o','*')
   when 'oo' then '' 
   when '*o' then '2:'
   when 'o*' then '1 '
   else '' end 
||case decode(n2,'o','o','*')||decode(n3,'o','o','*') when 'oo' then '' when '*o' then '3:'when 'o*' then '2 '   else '' end 
||case decode(n3,'o','o','*')||decode(n4,'o','o','*') when 'oo' then '' when '*o' then '4:'when 'o*' then '3 '   else '' end 
||case decode(n4,'o','o','*')||decode(n5,'o','o','*') when 'oo' then '' when '*o' then '5:'when 'o*' then '4 '   else '' end 
||case decode(n5,'o','o','*')||decode(n6,'o','o','*') when 'oo' then '' when '*o' then '6:'when 'o*' then '5 '   else '' end 
||case decode(n6,'o','o','*')||decode(n7,'o','o','*') when 'oo' then '' when '*o' then '7:'when 'o*' then '6 '   else '' end 
||case decode(n7,'o','o','*')||decode(n8,'o','o','*') when 'oo' then '' when '*o' then '8:'when 'o*' then '7 '   else '' end 
||case decode(n8,'o','o','*')||decode(n9,'o','o','*') when 'oo' then '' when '*o' then '9:'when 'o*' then '8 '   else '' end 
||case decode(n9,'o','o','*')||decode(n10,'o','o','*') when 'oo' then '' when '*o' then '10:'when 'o*' then '9 '   else '' end 
||case decode(n10,'o','o','*')||decode(n11,'o','o','*') when 'oo' then '' when '*o' then '11:'when 'o*' then '10 '   else '' end 
||case decode(n11,'o','o','*')||decode(n30,'o','o','*') when 'oo' then '' when '*o' then '30:'when 'o*' then '11 '   else '' end 
/*.. тут больше строк, недостающіе...........*/
||case decode(n30,'o','o','*')||decode(n31,'o','o','*') when 'oo' then '31' when '*o' then '31:31'when 'o*' then '30 '   else '' end 
str
,g.* from GRAFIK g
order by kod_sotr,god
/

STR                                KOD_SOTR        GOD N N N N N N N N N N N N N
-------------------------------- ---------- ---------- - - - - - - - - - - - - -
2:3 5:6 8:8 10:31                       111       2017   o o - o o   o   o o o o
1:4 9:30                                222       2018 o o o o S t a s o o o o
1:1 3:11 31:31                          333       2018 o   o o o o o o o o o x o




ps
если обязательно надо динамически, то продолжим
.....
stax
...
Рейтинг: 0 / 0
Поиск по строке
    #39421837
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94MaximaXXLNorman94,

иначе говоря, тут не решают задачи, а помогают в решении
пропущено...

Должна была Вам помочь более чем

Я написал работающий пример, рассказал что менять в соответствии с Вашими дополнениями

Но я не вправе решать что Вам брать и что оставить для решения конкретно Вашей задачи.
Проявите интеллект и подумайте ...

У меня такой глупый вопрос:
unpivot можно использовать с динамическим блоком?
да

динмика нужна в случаях
1) неизвестно имя таблицы
2) неизвестны столбцы (их к-во)
3) в других (не Ваш случай, напр неизвестный линк)

у Вас все определено
таблица -GRAFIK, столбцы N*
динамика в такой постановке не нужна

мож Вам нужно оформить в виде ф-ции?
то ето другой вопрос, используйте селесты в Вашей ф-ции

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

Нужна динамика, так как постоянно вручную набирать 52 столбца (которые характеризуют собой недели) устанешь быстро. Плюс, это одно из условии задачи. Я бы уже давно использовал UNPIVOT и не парился бы, но нет.

Есть таблица GRAFIK. В ней такие поля как id_sotr (код сотрудника), god (год) и 52 недели N1, N2, N3 (30 в шапке я написал для примера, но понял что это глупость). Значения недели могут быть У (обозначает учебный отпуск) Б (за свой счёт), и О (вне очередной). Интервалы первых двух отпусков встречаются лишь один раз (такое условие), и функции их вызова я сделал (пример в шапке). Теперь же нужна функция, которая динамическим прогоном и с помощью цикла находила два интервала отпуска (то есть первое количество недель и второе).

Блин, почему же я так сразу всё не пояснил, стыд то какой...

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

Нужна динамика, так как постоянно вручную набирать 52 столбца (которые характеризуют собой недели) устанешь быстро. Плюс, это одно из условии задачи. Я бы уже давно использовал UNPIVOT и не парился бы, но нет.

Есть таблица GRAFIK. В ней такие поля как id_sotr (код сотрудника), god (год) и 52 недели N1, N2, N3 (30 в шапке я написал для примера, но понял что это глупость). Значения недели могут быть У (обозначает учебный отпуск) Б (за свой счёт), и О (вне очередной). Интервалы первых двух отпусков встречаются лишь один раз (такое условие), и функции их вызова я сделал (пример в шапке). Теперь же нужна функция, которая динамическим прогоном и с помощью цикла находила два интервала отпуска (то есть первое количество недель и второе).

Блин, почему же я так сразу всё не пояснил, стыд то какой...

Спасибо вам, stax.

не вижу проблем набрать 51поле

если обязательное условие динамика
то
для MaximaXXL генерите with i in (N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11))
для моего варіанта case
для Вашего (із первого поста) может будет достаточно для разных букв (отпусков) брать разные разделители

если обязательное условие функция, то опишите требование, что должна вернуть ф-ция

приведите пример данных и что получитиь (вернуть) и
1) нужна ф-ция
2) достатотчно селекта

зы
на примере, мне легче понять что надо решить

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

Нужна динамика, так как постоянно вручную набирать 52 столбца (которые характеризуют собой недели) устанешь быстро. Плюс, это одно из условии задачи. Я бы уже давно использовал UNPIVOT и не парился бы, но нет.

Есть таблица GRAFIK. В ней такие поля как id_sotr (код сотрудника), god (год) и 52 недели N1, N2, N3 (30 в шапке я написал для примера, но понял что это глупость). Значения недели могут быть У (обозначает учебный отпуск) Б (за свой счёт), и О (вне очередной). Интервалы первых двух отпусков встречаются лишь один раз (такое условие), и функции их вызова я сделал (пример в шапке). Теперь же нужна функция, которая динамическим прогоном и с помощью цикла находила два интервала отпуска (то есть первое количество недель и второе).

Блин, почему же я так сразу всё не пояснил, стыд то какой...

Спасибо вам, stax.

не вижу проблем набрать 51поле

если обязательное условие динамика
то
для MaximaXXL генерите with i in (N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11))
для моего варіанта case
для Вашего (із первого поста) может будет достаточно для разных букв (отпусков) брать разные разделители

если обязательное условие функция, то опишите требование, что должна вернуть ф-ция

приведите пример данных и что получитиь (вернуть) и
1) нужна ф-ция
2) достатотчно селекта

зы
на примере, мне легче понять что надо решить

.....
stax

Ну вот смотрите, пример того, как я вытаскиваю интервал одного отпуска (учебного)

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
create or replace FUNCTION get_week_list1(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.mm')||'||''; '' ELSE NULL END ' ,'||') -- здесь идёт динамический перебор 52 столбцов,
---причём я отделяю те, что с N от остальных (кода сотрудника и года) и одновременно преобразую их в дату (день и месяц недели)
--- также здесь идёт проверка и вытаскиваются те слобцы, что имеют значения о
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;



Входными параметрами являются код сотрудника и год по которому я смотрю отпуск. Данная функция работает с одним интервалом недель, но если их две, то нет - он тупо выводит первую неделю первого интервала и последнюю неделю последнего интервала.

Кстати сам вызов идёт тут. Тут же идёт вычисление интервала
Код: plsql
1.
2.
SELECT t.god, t.kod_sotr, regexp_substr (get_week_list1(t.kod_sotr,t.god), '^([[:digit:]]+)(,)([[:digit:]]+)(;)') as week_first, 
regexp_substr (get_week_list1(t.kod_sotr,t.god), '([[:digit:]]+)(,)([[:digit:]]+)(;)$') as week_last FROM GRAFIK t;
...
Рейтинг: 0 / 0
Поиск по строке
    #39422110
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94...

Входными параметрами являются код сотрудника и год по которому я смотрю отпуск. Данная функция работает с одним интервалом недель, но если их две, то нет - он тупо выводит первую неделю первого интервала и последнюю неделю последнего интервала.

[/src]

буду отвечать частями
ето не так
1) добавить сортировку (если надо), иначе может случится так что 51я неделя будет не последней
ORDER BY 1 не сортирует, 1 ето не номер столбца, ето константа

2)функция работает с МНОГИМИ "нтервалами" недель (вернее она не интервалы выводит)

ф-ция вывовит недели где o
кстати Вы используете ww, непонятно зачем

Код: plsql
1.
2.
3.
4.
5.
6.
7.
SQL> select get_week_list1(kod_sotr,god) f,g.* from GRAFIK g;

F                                                                   GOD   KOD_SOTR N N N N N N N N N N
------------------------------------------------------------ ---------- ---------- - - - - - - - - - -
01.01; 15.01; 22.01; 29.01; 05.02; 12.02; 19.02; 05.03;            2017        222 o   o o o o o o   o
08.01; 15.01; 22.01; 29.01; 05.02; 12.02; 19.02; 05.03;            2017        202   o o o o o o o   o
01.01; 15.01; 29.01; 12.02; 26.02;                                 2017        111 o   o   o   o   o




авторКстати сам вызов идёт тут. Тут же идёт вычисление интервала
[src oracle]
SELECT t.god, t.kod_sotr, regexp_substr (get_week_list1(t.kod_sotr,t.god), '^([[:digit:]]+)(,)([[:digit:]]+)(;)') as week_first,
regexp_substr (get_week_list1(t.kod_sotr,t.god), '([[:digit:]]+)(,)([[:digit:]]+)(;)$') as week_last FROM GRAFIK t;

ф-ція не причем, она отрабытыват правильно
а от вычисление, если "интервал" не один у Вас неправильно, его (вызов/селект) надо переписывать
как, другой вопрос

так как у Вас "идёт вычисление интервала" всеравно в селекте, то ф-ция не нужна (кроме случая что она где-то еще используется)

Вам надо определится
1) нужна ли ф-ция, и если нужна то что она должна возвращать (напр сразу 08.01/19.02; 05.03/05.03);
2) если ф-ция нужна именно такая как есть, то переписать селект в котором "идёт вычисление интервала"
3) сделать селектом без ф-ции

зы
когда-то наш архитектор тоже график хотел сделать как у вас но поденный
мне повезло, что в старых версиях оракля табличку с 370полями создать было невозможно


pss
еще раз динамика СДЕСЬ не нужна, перечислить 51 case не проблема
аргумент я віжу токо один
начальник требует через динамику! (Я СКАЗАЛ!!!)

.....
stax
...
Рейтинг: 0 / 0
Поиск по строке
    #39422112
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stax..еще раз динамика СДЕСЬ не нужна, перечислить 51 case не проблемаДа просто ненормализованному горе-дизайнеру ноги повыдёргивать нужно.
...
Рейтинг: 0 / 0
Поиск по строке
    #39422134
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94MaximaXXLNorman94,

иначе говоря, тут не решают задачи, а помогают в решении
пропущено...

Должна была Вам помочь более чем

Я написал работающий пример, рассказал что менять в соответствии с Вашими дополнениями

Но я не вправе решать что Вам брать и что оставить для решения конкретно Вашей задачи.
Проявите интеллект и подумайте ...

У меня такой глупый вопрос:
unpivot можно использовать с динамическим блоком?
можно

подчеркиваю, Вам не нужен "динамический блок"
привожу просто для примера, надеюсь MaximaXXL не обидется
надо причесать, так-как ф-ция выполняется для ОДНОЙ строки то
god,kod_sotr возможно из PARTITION/order by/group by убрать

не убирал, дублировал влоб пример Максима

Код: 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.
  1  create or replace FUNCTION
  2   get_week_list2(i_code IN INTEGER, i_year in integer)
  3  RETURN VARCHAR2 IS
  4   l_list VARCHAR2(32767);
  5   l_res VARCHAR2(4000);
  6  BEGIN
  7   SELECT listagg(column_name,',') WITHIN GROUP(ORDER BY to_number(LTRIM(column_name,'N')))
  8   INTO l_list
  9   FROM user_tab_columns
 10   WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
 11   l_list:='with t2 as(
 12   select God, Kod_sotr,'||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year)'||
 13  q'~
 14  select /* God, Kod_sotr, */ listagg(lag_WN) within group (order by RN,Kod_sotr) vacation
 15  from (
 16  select rownum RN, God, Kod_sotr,
 17  case when lead(Week_Number) over(PARTITION by God order by Kod_sotr) - Week_number > 1 then Weeks||';'
 18       when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||';'
 19       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||','
 20       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then Weeks||','
 21       else null end lag_WN
 22          from (
 23                  select God, Kod_sotr, weeks, Vacation, cast(ltrim(weeks,'N')as number) Week_Number from t2
 24                  unpivot (vacation for weeks in (~'||l_list||q'~))
 25                  order by God, Kod_sotr, cast(ltrim(weeks,'N')as number)
 26                )
 27          )group by god, Kod_sotr~';
 28  EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
 29  RETURN RTRIM(l_res);
 30* END;
SQL> /

Function created.

SQL> select get_week_list2( kod_sotr,god) f,g.* from grafik g;

F                           GOD   KOD_SOTR N N N N N N N N N N
-------------------- ---------- ---------- - - - - - - - - - -
N1;N3,N8;N10;              2017        222 o   o o o o o o   o
N2,N8;N10;                 2017        202   o o o o o o o   o
N1;N3;N5;N7;N9;            2017        111 o   o   o   o   o


SQL> desc grafik
 Name                                      Null?    Type
 ----------------------------------------- -------- -------------
 GOD                                                NUMBER(38)
 KOD_SOTR                                           NUMBER(38)
 N1                                                 VARCHAR2(1)
 N2                                                 VARCHAR2(1)
 N3                                                 VARCHAR2(1)
 N4                                                 VARCHAR2(1)
 N5                                                 VARCHAR2(1)
 N6                                                 VARCHAR2(1)
 N7                                                 VARCHAR2(1)
 N8                                                 VARCHAR2(1)
 N9                                                 VARCHAR2(1)
 N10                                                VARCHAR2(1)
...
Рейтинг: 0 / 0
Поиск по строке
    #39422142
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elicstax..еще раз динамика СДЕСЬ не нужна, перечислить 51 case не проблемаДа просто ненормализованному горе-дизайнеру ноги повыдёргивать нужно.
мне тоже

когда-то я делал графік за месяц (на третем формсе )
сотрудник,1-28/30/31 день в одну строку,
табельщику удобно было работать с таблицей
tn,dat (год.месяц),d1,d2,...,d31 для визуализации

а от с tn,dat_tabel (день.год.месяц) геморой был в формсах/репорте

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


У меня такой глупый вопрос:
unpivot можно использовать с динамическим блоком?
можно

подчеркиваю, Вам не нужен "динамический блок"
привожу просто для примера, надеюсь MaximaXXL не обидется
надо причесать, так-как ф-ция выполняется для ОДНОЙ строки то
god,kod_sotr возможно из PARTITION/order by/group by убрать

не убирал, дублировал влоб пример Максима

Код: 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.
  1  create or replace FUNCTION
  2   get_week_list2(i_code IN INTEGER, i_year in integer)
  3  RETURN VARCHAR2 IS
  4   l_list VARCHAR2(32767);
  5   l_res VARCHAR2(4000);
  6  BEGIN
  7   SELECT listagg(column_name,',') WITHIN GROUP(ORDER BY to_number(LTRIM(column_name,'N')))
  8   INTO l_list
  9   FROM user_tab_columns
 10   WHERE TABLE_NAME = 'GRAFIK' AND column_name LIKE 'N%';
 11   l_list:='with t2 as(
 12   select God, Kod_sotr,'||l_list||' FROM GRAFIK WHERE kod_sotr=:A AND god=:year)'||
 13  q'~
 14  select /* God, Kod_sotr, */ listagg(lag_WN) within group (order by RN,Kod_sotr) vacation
 15  from (
 16  select rownum RN, God, Kod_sotr,
 17  case when lead(Week_Number) over(PARTITION by God order by Kod_sotr) - Week_number > 1 then Weeks||';'
 18       when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||';'
 19       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||','
 20       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then Weeks||','
 21       else null end lag_WN
 22          from (
 23                  select God, Kod_sotr, weeks, Vacation, cast(ltrim(weeks,'N')as number) Week_Number from t2
 24                  unpivot (vacation for weeks in (~'||l_list||q'~))
 25                  order by God, Kod_sotr, cast(ltrim(weeks,'N')as number)
 26                )
 27          )group by god, Kod_sotr~';
 28  EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
 29  RETURN RTRIM(l_res);
 30* END;
SQL> /

Function created.

SQL> select get_week_list2( kod_sotr,god) f,g.* from grafik g;

F                           GOD   KOD_SOTR N N N N N N N N N N
-------------------- ---------- ---------- - - - - - - - - - -
N1;N3,N8;N10;              2017        222 o   o o o o o o   o
N2,N8;N10;                 2017        202   o o o o o o o   o
N1;N3;N5;N7;N9;            2017        111 o   o   o   o   o


SQL> desc grafik
 Name                                      Null?    Type
 ----------------------------------------- -------- -------------
 GOD                                                NUMBER(38)
 KOD_SOTR                                           NUMBER(38)
 N1                                                 VARCHAR2(1)
 N2                                                 VARCHAR2(1)
 N3                                                 VARCHAR2(1)
 N4                                                 VARCHAR2(1)
 N5                                                 VARCHAR2(1)
 N6                                                 VARCHAR2(1)
 N7                                                 VARCHAR2(1)
 N8                                                 VARCHAR2(1)
 N9                                                 VARCHAR2(1)
 N10                                                VARCHAR2(1)



Здорово, то что надо, спасибо! Однако я никак не могу понять, куда можно вставить то, чтобы он искал и выявлял интервалы связанные только с "о".

Возвращать он должен именно интервалы "о" по типу "01.02; 01.02". То есть как вы сделали.

Да, динамику требует начальство, сам бы давно UNPIVOT воспользовался и не парил себе мозги.
...
Рейтинг: 0 / 0
Поиск по строке
    #39422191
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94Здорово, то что надо, спасибо! Однако я никак не могу понять, куда можно вставить то, чтобы он искал и выявлял интервалы связанные только с "о".

Возвращать он должен именно интервалы "о" по типу "01.02; 01.02". То есть как вы сделали.

Да, динамику требует начальство, сам бы давно UNPIVOT воспользовался и не парил себе мозги.

дивно, но бог с ними (начальниками)

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
...
                  order by God, Kod_sotr, cast(ltrim(weeks,'N')as number)
                ) where vacation='o'
...
SQL> select get_week_list2( kod_sotr,god) f,g.* from grafik g;

F                           GOD   KOD_SOTR N N N N N N N N N N
-------------------- ---------- ---------- - - - - - - - - - -
N1;N3,N4;N6,N8;N10;        2017        222 o   o o y o o o   o
N2,N4;N6,N8;N10;           2017        202   o o o y o o o   o
N1;N3;N7;N9;               2017        111 o   o   y   o   o



Запрос MaximaXXL я не рассматриваю (обсуждаю), Вам решать
напр я б сортировку cast(ltrim(weeks,'N')as number) добавил в аналитику


зы
можно (и надо) на ты

......
stax
...
Рейтинг: 0 / 0
Поиск по строке
    #39422208
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
stax..Запрос MaximaXXL я не рассматриваю (обсуждаю), Вам решать
напр я б сортировку cast(ltrim(weeks,'N')as number) добавил в аналитику


зы
можно (и надо) на ты

Беда подкралась незаметно - он null выдает

Код: 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.
create or replace FUNCTION
 week_fun(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_number(LTRIM(column_name,'N')))
 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||';'
      when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||';'
       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||','
       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then Weeks||','
       else null end lag_WN
          from (
                   select God, Kod_sotr, weeks, 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='o'
          )group by god, Kod_sotr~';
   EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
  RETURN RTRIM(l_res);
  END;
...
Рейтинг: 0 / 0
Поиск по строке
    #39422210
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
stax..,

А не, всё норм, это я ступил, забыл раскладку переключить. Вот. Отлично. То, что надо. Спасибо тебе, огромное!
...
Рейтинг: 0 / 0
Поиск по строке
    #39422214
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94stax..,

А не, всё норм, это я ступил, забыл раскладку переключить. Вот. Отлично. То, что надо. Спасибо тебе, огромное!
если нет проверки, код "о" неудачно выбрали, легко спутать с О,0,o,O

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

А не, всё норм, это я ступил, забыл раскладку переключить. Вот. Отлично. То, что надо. Спасибо тебе, огромное!
если нет проверки, код "о" неудачно выбрали, легко спутать с О,0,o,O

....
stax

У меня ещё к вам небольшой вопрос. Теперь я пытаюсь преобразовать названия столбцов в дату, чтобы получилось число и месяц начала любой недели. Я подставляю этот рассчёт в эту функцию

Код: 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.
create or replace FUNCTION
 week_fun1(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_number(LTRIM(column_name,'N')))
 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||';'
      when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||';'
       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||','
       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then Weeks||','
       else null end lag_WN
          from (
                   select God, Kod_sotr, weeks, Vacation, cast(to_char( trunc (to_date(~'||i_year||q'~||'0101', 'yyyymmdd') 
+ ((LTRIM(weeks,'N'))-1)*7, 'ww'), 'dd.mm')as number) Week_Number from t2
                  unpivot (vacation for weeks in (~'||l_list||q'~))
                 order by God, Kod_sotr, cast(to_char( trunc (to_date(~'||i_year||q'~||'0101', 'yyyymmdd') 
+ ((LTRIM(weeks,'N'))-1)*7, 'ww'), 'dd.mm')as number)
                )
          )group by god, Kod_sotr~';
   EXECUTE IMMEDIATE l_list INTO l_res USING i_code,i_year;
  RETURN RTRIM(l_res);
  END;



Но он пишет неверное число. В чём может быть дело?
...
Рейтинг: 0 / 0
Поиск по строке
    #39422805
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Теперь я немного видоизменил код, но он выдаёт по прежнему как N1, N2 и т.д., а должен как 01.01, 02.01

Код: 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.
create or replace FUNCTION
 week_fun1(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( trunc (to_date(i_year||'0101', 'yyyymmdd') 
+ ((LTRIM(column_name,'N'))-1)*7, 'ww'), 'dd.mm'))
 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||';'
      when lead(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||';'
       when lag(Week_Number) over(PARTITION by God order by Kod_sotr) is null then Weeks||','
       when Week_number - lag(Week_Number) over(PARTITION by God order by Kod_sotr) > 1 then Weeks||','
       else null end lag_WN
          from (
                   select God, Kod_sotr, weeks, 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
Поиск по строке
    #39423179
MaximaXXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Norman94Теперь я немного видоизменил код, но он выдаёт по прежнему как N1, N2 и т.д., а должен как 01.01, 02.01


он выдаёт по прежнему как N1, N2 и т.д., а должен как 01.01, 02.01 - ну наверно не заменил в нужном месте =)

Я бы если по быстрому заменил бы в корне

Код: 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.
create or replace FUNCTION
 week_fun1(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( trunc (to_date(i_year||'0101', 'yyyymmdd') 
+ ((LTRIM(column_name,'N'))-1)*7, 'ww'), 'dd.mm'))
 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(trunc(to_date(god,'yyyy'),'y')+(cast(ltrim(weeks,'N') as number)-1)*7,'dd.mm') 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;


т.е. во внутр селекте выводим не weeks а сразу даты
to_char(trunc(to_date(god,'yyyy'),'y')+(cast(ltrim(weeks,'N') as number)-1)*7,'dd.mm') Weeks_D,
ну а потом их собираем в диапазоны
...
Рейтинг: 0 / 0
Поиск по строке
    #39423186
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MaximaXXLNorman94Теперь я немного видоизменил код, но он выдаёт по прежнему как N1, N2 и т.д., а должен как 01.01, 02.01


он выдаёт по прежнему как N1, N2 и т.д., а должен как 01.01, 02.01 - ну наверно не заменил в нужном месте =)

Я бы если по быстрому заменил бы в корне

Код: 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.
create or replace FUNCTION
 week_fun1(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( trunc (to_date(i_year||'0101', 'yyyymmdd') 
+ ((LTRIM(column_name,'N'))-1)*7, 'ww'), 'dd.mm'))
 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(trunc(to_date(god,'yyyy'),'y')+(cast(ltrim(weeks,'N') as number)-1)*7,'dd.mm') 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;



т.е. во внутр селекте выводим не weeks а сразу даты
to_char(trunc(to_date(god,'yyyy'),'y')+(cast(ltrim(weeks,'N') as number)-1)*7,'dd.mm') Weeks_D,
ну а потом их собираем в диапазоны

Он всё равно выдаёт invalid number
...
Рейтинг: 0 / 0
Поиск по строке
    #39423188
Norman94
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Norman94,

А не, всё правильно, это я чуть тупанул. Ну блин, долго же до этого доходило, аж обидно слегка(

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

А не, всё правильно, это я чуть тупанул. Ну блин, долго же до этого доходило, аж обидно слегка(

Спасибо огромное)

Ну а теперь, когда все получилось бери надфилек и начинай выкидывать ненужное =)
Код: plsql
1.
2.
3.
4.
5.
  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



меняй на
Код: plsql
1.
2.
3.
  case when lead(Week_Number,1,100) over(PARTITION by God order by Kod_sotr) - Week_number > 1 then Weeks_D||';'
       when Week_number - lag(Week_Number,1,0) over(PARTITION by God order by Kod_sotr) > 1 then  Weeks_D||','
       else null end lag_WN


и комментируй на будущее
cast(... as number) на to_number(...)
выкидывание ненужных для твоего случая order ...
...
Рейтинг: 0 / 0
49 сообщений из 49, показаны все 2 страниц
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Поиск по строке
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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