Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Поиск по строке / 25 сообщений из 49, страница 1 из 2
17.03.2017, 07:59
    #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
17.03.2017, 08:01
    #39421159
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
Norman94, в шапке неправильно таблица сделана, вот как
...
Рейтинг: 0 / 0
17.03.2017, 09:42
    #39421207
env
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
17.03.2017, 09:53
    #39421226
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
env,
спасибо за форматирование, буду исправляться

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

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

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

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

Я хотел так сделать, беда в том, что у меня динамический прогон по столбцам с помощью column_table.
...
Рейтинг: 0 / 0
17.03.2017, 12:10
    #39421384
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
Возник ещё вопрос. Так как мне остро необходимо использовать динамический прогон, имеется ли возможность привязать UNPIVOT к вызову функции?
...
Рейтинг: 0 / 0
17.03.2017, 12:28
    #39421406
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
А можно как то указать, если после значения следует пустая ячейка, то она должна быть последней в интервале? Или наоборот, если до неё есть пустые ячейки, то первый? Я сколько не читал про regexp_substr, ничего толкого не нашёл. Может кто что подсказать по поводу этого?
...
Рейтинг: 0 / 0
17.03.2017, 12:31
    #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
17.03.2017, 12:31
    #39421414
env
env
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
Norman94Возник ещё вопрос. Так как мне остро необходимо использовать динамический прогон, имеется ли возможность привязать UNPIVOT к вызову функции?

Чем вызвана такая необходимость? Если есть возможность обойтись без динамического sql - лучше воспользоватся ей.
...
Рейтинг: 0 / 0
17.03.2017, 12:36
    #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
17.03.2017, 12:37
    #39421419
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
envNorman94Возник ещё вопрос. Так как мне остро необходимо использовать динамический прогон, имеется ли возможность привязать UNPIVOT к вызову функции?

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

Необходимость заключается в том, что столбцов куча, они различаются лишь числовым порядком, и их значение может меняться. К сожалению без динамики нельзя.
...
Рейтинг: 0 / 0
17.03.2017, 12:51
    #39421435
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
Если что, таблица выгдядит таким образом
...
Рейтинг: 0 / 0
17.03.2017, 13:53
    #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
17.03.2017, 14:00
    #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
17.03.2017, 14:06
    #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
17.03.2017, 14:12
    #39421523
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
Norman94,
Вы случайно не Аналитик по профессии?
Вы поставили задачу, я ее решил.

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

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

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

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

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

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

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

В данной задаче нет никакой необходимости в динамических запросах.
...
Рейтинг: 0 / 0
17.03.2017, 14:34
    #39421545
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
envВ данной задаче нет никакой необходимости в динамических запросах.
В моём случае к сожалению есть.
...
Рейтинг: 0 / 0
17.03.2017, 14:59
    #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
17.03.2017, 15:04
    #39421601
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
MaximaXXL,

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

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

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

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

Но я не вправе решать что Вам брать и что оставить для решения конкретно Вашей задачи.
Проявите интеллект и подумайте ...
...
Рейтинг: 0 / 0
17.03.2017, 15:17
    #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
17.03.2017, 15:19
    #39421634
Norman94
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Поиск по строке
MaximaXXLNorman94,

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

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

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

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

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


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