CftClub.ru
Клуб специалистов ЦФТ-Банк

Обработка таблицы MAIN_DOCUM
На страницу 1, 2, 3  След.
 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Банковская отчетность (оперативная, обязательная, Oracle Reports)
Предыдущая тема :: Следующая тема  
Автор Сообщение
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 08:27   Обработка таблицы MAIN_DOCUM Ответить с цитатой
Полезность: Нет оценки
Всем доброго дня.

Вопрос такой:
Есть отчет со многими колонками
Всем нравится
Но стал очень громоздким - по многим причинам

Много приходится делать циклов типа

for(select md1 (sum(md1.[SUM]) : m_sum,
(case when md1.[KL_KT].[0] = 1
then substr(md1.[KL_KT].[1].[2].[MAIN_V_ID],1,5)
else substr(md1.[KL_KT].[2].[1],1,5)
end) : debet_oborot_str)
in ::[MAIN_DOCUM] all
where md1.[ACC_DT] = c.[af_id]
and (md1.[DATE_PROV] >= DATE_BEGIN)
and (md1.[DATE_PROV] <= DATE_END)
and md1%state='PROV'
group by (case when md1.[KL_KT].[0] = 1
then substr(md1.[KL_KT].[1].[2].[MAIN_V_ID],1,5)
else substr(md1.[KL_KT].[2].[1],1,5)
end)
order by 1 desc)
loop
if debet_oborot >0 then
debet_oborot_str := debet_oborot_str||md1.debet_oborot_str||to_char(md1.m_sum,'999999999999999.99')||'('||to_char(md1.m_sum/debet_oborot*100,'999.99')||'%)'||chr(10);
end if;
end loop;

debet_oborot_str:=debet_oborot_str||'Итого: '||to_char(debet_oborot,'999999999999999.99');


Придумать можно что-то?
Результат отчета прилагаю.
Скорее вопрос больше административный.
Volod
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеВт Апр 10, 2018 09:36    Ответить с цитатой
Полезность: Нет оценки
Все колонки вычислять в одном селекте.
Что значит громоздкий - 2 часа считает?
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 09:55    Ответить с цитатой
Полезность: Нет оценки
Селекты там разные
Вот второй

for(select md (sum(md.[SUM]) :m_sum)
in ::[MAIN_DOCUM] all
where md.[ACC_DT] = c.[af_id]
and md.[DATE_PROV] >= DATE_BEGIN
and md.[DATE_PROV] <= DATE_END
and md%state = 'PROV'
and (substr(md.[KL_KT].[1].[2].[MAIN_V_ID],1,5) = '40101' or
substr(md.[KL_KT].[2].[1],1,5) = '40101'))
loop
begin
nalog_oborot := md.m_sum;
exception when NO_DATA_FOUND or TOO_MANY_ROWS then
nalog_oborot := nalog_oborot;
end;
exit;
end loop;


Не 2 часа, но долго, если по многим организациям запустить.
С полчаса по приличной выборке.
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 09:56    Ответить с цитатой
Полезность: Нет оценки
А таких селектов порядка 10
Запускаются по каждой организации.
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 09:58    Ответить с цитатой
Полезность: Нет оценки
Хотя может и правда - сделать один селект, а внутри if делать.
pas
Профи


Вступление в Клуб: 20.11.2007
СообщениеВт Апр 10, 2018 11:01    Ответить с цитатой
Полезность: Нет оценки
401 счетов много?

Лучше селект делать через выписку, быстрее будет.
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 11:09    Ответить с цитатой
Полезность: Нет оценки
pas пишет:
401 счетов много?

Лучше селект делать через выписку, быстрее будет.


Не много, но есть. Другие селекты посложнее. Там и по назначениям платежей есть.

А пример через выписку сможешь предложить?
Alkov
Профи


Вступление в Клуб: 23.09.2010
СообщениеВт Апр 10, 2018 11:48    Ответить с цитатой
Полезность: Нет оценки
Вообще план надо смотреть, в идеале трейс , какой индекс цепляется,
большой ли период обычно по P_DATE_DEIGIN - P_DATE_END...

вот тут например substr(md.[KL_KT].[1].[2].[MAIN_V_ID],1,5) = '40101'
substr отключает индекс специально ?
, можно же было сделать md.[KL_KT].[1].[2].[MAIN_V_ID] like '40101%'
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 13:10    Ответить с цитатой
Полезность: Нет оценки
Я понимаю, что индескс наверное не тот.
Очень много конструкций OR.
Выслал все, что есть.
Volod
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеВт Апр 10, 2018 14:45    Ответить с цитатой
Полезность: Нет оценки
Дело не в индексе.
Это простая операция или групповая?
Практически все обороты можно посчитать в одном селекте.
Максимально убрать интерфейсные вызовы.
if CLIENT is not null then - не использовать переменные = наименованию типов/реквизитов.
Не использовать однобуквенные алиасы - их найти по тексту затруднительно.
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 15:02    Ответить с цитатой
Полезность: Нет оценки
Операция простая.
Отчет выводится на основании фильтров.
Подразделение, клиент, группа риска(внутренняя - доп.поле)

Интерфейсные вызовы лучше в переменные засунуть?
Volod
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеВт Апр 10, 2018 15:55    Ответить с цитатой
Полезность: Нет оценки
Интерфейсные вызовы нужно заменить на вычисление колонок в соответствующем селекте
r1.[C_ORG].[PARTNER].[NAME]
r1.[C_ORG].[RANGE].[VALUE]
c.[af_id].[MAIN_V_ID]

r.[C_ORG].[ALL_BOSS] is not null - тут правильно %size(1) > 0
if r.[C_ORG].[LINKS_OTHER] is not null - тут правильно %size(1) > 0
и смысл вообще проверять, если дальше select loop
Volod
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеВт Апр 10, 2018 16:39    Ответить с цитатой
Полезность: Нет оценки
Здесь могут тормоза - LEGAL_161P м.б. немаленькая таблица.
Есть же ссылка на клиента в BLOCK_ARR
Код:
                     for   
                        (select l1(l1 : l1_id)
                         in ::[LEGAL_161P]
                         where l1.vo=1984365)
                     loop
                        if ::[LEGAL_161P].[Z134021099].get_payer_inn(l1.l1_id)=c.[c_inn] or ::[LEGAL_161P].[Z134021099].get_recip_inn(l1.l1_id)=c.[c_inn] then
                           c_Number_Doc_Ostanov_str := '6001. Код подозрительных операций.';
                           exit;
                        end if;
                     end loop;
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 17:30    Ответить с цитатой
Полезность: Нет оценки
Volod пишет:
Здесь могут тормоза - LEGAL_161P м.б. немаленькая таблица.
Есть же ссылка на клиента в BLOCK_ARR
Код:
                     for   
                        (select l1(l1 : l1_id)
                         in ::[LEGAL_161P]
                         where l1.vo=1984365)
                     loop
                        if ::[LEGAL_161P].[Z134021099].get_payer_inn(l1.l1_id)=c.[c_inn] or ::[LEGAL_161P].[Z134021099].get_recip_inn(l1.l1_id)=c.[c_inn] then
                           c_Number_Doc_Ostanov_str := '6001. Код подозрительных операций.';
                           exit;
                        end if;
                     end loop;



Там по одному клиенту только работает. Если выбран. По многим клиентам действительно долго.
mmm_kazan
Участник со стажем


Вступление в Клуб: 28.03.2018
СообщениеВт Апр 10, 2018 17:32    Ответить с цитатой
Полезность: Нет оценки
Volod пишет:
Интерфейсные вызовы нужно заменить на вычисление колонок в соответствующем селекте
r1.[C_ORG].[PARTNER].[NAME]
r1.[C_ORG].[RANGE].[VALUE]
c.[af_id].[MAIN_V_ID]

r.[C_ORG].[ALL_BOSS] is not null - тут правильно %size(1) > 0
if r.[C_ORG].[LINKS_OTHER] is not null - тут правильно %size(1) > 0
и смысл вообще проверять, если дальше select loop


А такой вариант интерфейсных вызовов может тормозить? Я считал что объект имею - к его свойствам быстро доступ происходит.
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Банковская отчетность (оперативная, обязательная, Oracle Reports) Часовой пояс: GMT + 3
На страницу 1, 2, 3  След.
Страница 1 из 3

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru