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

Список работающих счетов

 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle
Предыдущая тема :: Следующая тема  
Автор Сообщение
mike24
Участник со стажем


Вступление в Клуб: 24.08.2012
СообщениеВт Июл 29, 2014 06:17   Список работающих счетов Ответить с цитатой
Полезность: Нет оценки
Коллеги, помогите оптимально получить список работающих счетов за период...
Запрос
Код:

select distinct a(a.[ACC_CORR] : a_acc) in ::[RECORDS] all
where a.[DATE] >= dat1 and a.[DATE] <= dat2

имеет очень высокую стоимость
Reddom
Участник со стажем


Вступление в Клуб: 25.01.2013
СообщениеВт Июл 29, 2014 08:27    Ответить с цитатой
Полезность: Нет оценки
У счета есть реквизит DATE_LAST (Дата последней операции по счету). По счетам искать легче (AC_FIN) и distinct делать не надо
mike24
Участник со стажем


Вступление в Клуб: 24.08.2012
СообщениеВт Июл 29, 2014 08:50    Ответить с цитатой
Полезность: Нет оценки
DATE_LAST не подходит т.к. тербуется построить остатки и обороты по счетам за каждую дату из интервала дат. Счетов очень много, по всем бежать с f.a() долго.
вышел из положения так
Код:
select a(a.[ACC_DT] : a_acc) in ::[MAIN_DOCUM]
where a%STATE = 'PROV' and a.[DATE_PROV] >= dat1 and a.[DATE_PROV] <= dat2
union
select b(b.[ACC_KT] : a_acc) in ::[MAIN_DOCUM]
where b%STATE = 'PROV' and b.[DATE_PROV] >= dat1 and b.[DATE_PROV] <= dat2

работает почти в 2 раза быстрее, чем по RECORDS потому что в MAIN_DOCUM есть индексы по ACC_DT и АСС_КТ.
Может быть еще как-нибудь можно выкрутится? Гуру, посоветуйте плиз
Amper
Профи


Вступление в Клуб: 29.10.2010
СообщениеВт Июл 29, 2014 09:44   Re: Список работающих счетов Ответить с цитатой
Полезность: 1
mike24 пишет:
Коллеги, помогите оптимально получить список работающих счетов за период...
Запрос
Код:

select distinct a(a.[ACC_CORR] : a_acc) in ::[RECORDS] all
where a.[DATE] >= dat1 and a.[DATE] <= dat2

имеет очень высокую стоимость

Может быть так:
Код:
select acc.ID
from Z#AC_FIN acc
where exists
        (
            select 1
            from Z#RECORDS rec
            where   rec.COLLECTION_ID = acc.c_Arc_Move
                and rec.C_DATE >= dat1
                and rec.C_DATE <= dat2
        )
Reddom
Участник со стажем


Вступление в Клуб: 25.01.2013
СообщениеВт Июл 29, 2014 10:01    Ответить с цитатой
Полезность: 1
mike24 пишет:
DATE_LAST не подходит т.к. тербуется построить остатки и обороты по счетам за каждую дату из интервала дат. Счетов очень много, по всем бежать с f.a() долго.
вышел из положения так


Если период произвольный и необходимо найти остатки и обороты, то лучше подсчитать в RECORDS с помощью аналитических функций либо сумм с группировками по дате (зависит от задачи).

Опиши конкретно задачу, я попробую написать тебе запрос.
mike24
Участник со стажем


Вступление в Клуб: 24.08.2012
СообщениеВт Июл 29, 2014 10:15   Re: Список работающих счетов Ответить с цитатой
Полезность: Нет оценки
Amper пишет:
Может быть так:
Код:
select acc.ID
from Z#AC_FIN acc
where exists
        (
            select 1
            from Z#RECORDS rec
            where   rec.COLLECTION_ID = acc.c_Arc_Move
                and rec.C_DATE >= dat1
                and rec.C_DATE <= dat2
        )


Александр, спасибо! Слона-то я и не приметил Smile

Код:
select x(x%id : x_id
, abs(f.a_saldo_short(dat_ost+1, x, 'С', false )) : ost_out
, abs(f.a_saldo_short(dat_ost+1, x, 'С', true )) : ost_out_nt
, f.a_turn_short(dat_ost, dat_ost, x, true, false ) : turn_dt
, f.a_turn_short(dat_ost, dat_ost, x, false, false ) : turn_kt
, f.a_turn_short(dat_ost, dat_ost, x, true, true ) : turn_dt_nt
, f.a_turn_short(dat_ost, dat_ost, x, false, true ) : turn_kt_nt )
in ::[AC_FIN]
where exists (
   select rec(null) in ::[RECORDS] collections
   where rec%collection = x.[ARC_MOVE]
   and rec.[DATE] >= dat1 and rec.[DATE] <= dat2
   )

получился самый быстрый! Скорость приемлема.
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеВт Июл 29, 2014 14:15    Ответить с цитатой
Полезность: Нет оценки
Reddom пишет:
Если период произвольный и необходимо найти остатки и обороты, то лучше подсчитать в RECORDS с помощью аналитических функций...

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

Объясни мне, зачем?
Ну зачем здесь нужна эта неподъёмная блажь?
maestro
Профи


Вступление в Клуб: 12.10.2010
СообщениеСр Июл 30, 2014 17:45    Ответить с цитатой
Полезность: 2
Random пишет:
Reddom пишет:
Если период произвольный и необходимо найти остатки и обороты, то лучше подсчитать в RECORDS с помощью аналитических функций...

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

Объясни мне, зачем?
Ну зачем здесь нужна эта неподъёмная блажь?


Я бы написал именно на аналитике Smile (ЦФТшной аналитике, на самом деле это агрегат)


Код:

select x(
 x%id : x_id
,abs(analytic(max(rec.[START_SUM] + rec.[SUMMA]), 'KEEP (DENSE_RANK LAST ORDER BY [1], [2])', rec.[DATE], rec.[STAMP])) : out_saldo
,abs(analytic(max(rec.[START_SUM_NAT] + rec.[SUMMA_NAT]), 'KEEP (DENSE_RANK LAST ORDER BY [1], [2])', rec.[DATE], rec.[STAMP])) : out_saldo_nt
,sum(decode(rec.[DT],'1',rec.[SUMMA], 0)) : turn_dt
,sum(decode(rec.[DT],'1',rec.[SUMMA_NAT], 0)) : turn_dt_nt
,sum(decode(rec.[DT],'0',rec.[SUMMA], 0)) : turn_kt
,sum(decode(rec.[DT],'0',rec.[SUMMA_NAT], 0)) : turn_kt_nt
)
in ::[AC_FIN] , (x.[ARC_MOVE] : rec)
where rec.[DATE] >= dat1 and rec.[DATE] < dat2 + 1
group by x%id
mike24
Участник со стажем


Вступление в Клуб: 24.08.2012
СообщениеЧт Июл 31, 2014 05:40    Ответить с цитатой
Полезность: Нет оценки
maestro пишет:

Я бы написал именно на аналитике Smile (ЦФТшной аналитике, на самом деле это агрегат)

Код:

select x(
 x%id : x_id
,abs(analytic(max(rec.[START_SUM] + rec.[SUMMA]), 'KEEP (DENSE_RANK LAST ORDER BY [1], [2])', rec.[DATE], rec.[STAMP])) : out_saldo
,abs(analytic(max(rec.[START_SUM_NAT] + rec.[SUMMA_NAT]), 'KEEP (DENSE_RANK LAST ORDER BY [1], [2])', rec.[DATE], rec.[STAMP])) : out_saldo_nt
,sum(decode(rec.[DT],'1',rec.[SUMMA], 0)) : turn_dt
,sum(decode(rec.[DT],'1',rec.[SUMMA_NAT], 0)) : turn_dt_nt
,sum(decode(rec.[DT],'0',rec.[SUMMA], 0)) : turn_kt
,sum(decode(rec.[DT],'0',rec.[SUMMA_NAT], 0)) : turn_kt_nt
)
in ::[AC_FIN] , (x.[ARC_MOVE] : rec)
where rec.[DATE] >= dat1 and rec.[DATE] < dat2 + 1
group by x%id


maestro , спасибо, очень интересно!
Аналитические функции - это, конечно, здорово.
Проверил скорость - оба запроса работают одинаково, в районе 8 минут на месячном интервале (разница в секунды).
Так что я склоняюсь к первому варианту как к более простому и понятному Smile
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеЧт Июл 31, 2014 06:01    Ответить с цитатой
Полезность: Нет оценки
maestro пишет:
Random пишет:
Reddom пишет:
Если период произвольный и необходимо найти остатки и обороты, то лучше подсчитать в RECORDS с помощью аналитических функций...

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

Объясни мне, зачем?
Ну зачем здесь нужна эта неподъёмная блажь?


Я бы написал именно на аналитике Smile (ЦФТшной аналитике, на самом деле это агрегат)


Код:

select x(
 x%id : x_id
,abs(analytic(max(rec.[START_SUM] + rec.[SUMMA]), 'KEEP (DENSE_RANK LAST ORDER BY [1], [2])', rec.[DATE], rec.[STAMP])) : out_saldo
,abs(analytic(max(rec.[START_SUM_NAT] + rec.[SUMMA_NAT]), 'KEEP (DENSE_RANK LAST ORDER BY [1], [2])', rec.[DATE], rec.[STAMP])) : out_saldo_nt
,sum(decode(rec.[DT],'1',rec.[SUMMA], 0)) : turn_dt
,sum(decode(rec.[DT],'1',rec.[SUMMA_NAT], 0)) : turn_dt_nt
,sum(decode(rec.[DT],'0',rec.[SUMMA], 0)) : turn_kt
,sum(decode(rec.[DT],'0',rec.[SUMMA_NAT], 0)) : turn_kt_nt
)
in ::[AC_FIN] , (x.[ARC_MOVE] : rec)
where rec.[DATE] >= dat1 and rec.[DATE] < dat2 + 1
group by x%id


Согласен.
Хороший пример.

Хотя я бы использовал decode или case.
При этом чую я, что в данном случае аналитическая функция проще в поддержке даже.

Однако, если обороты не нужны - то аналитическая функция совершенно лишняя. Но выкрутиться можно - например, использовать хинт и ограничение and rownum < 2.

Код:

select a(

 (select /*index IDX_НЕ_ПОМНЮ_ТОЧНО_STAMP*/ v(
 v.[START_SUM]
) in a.[ARC_MOVE] where rownum < 2 and v.date входит в период ) :это входящий остаток

, (select /*index_desc IDX_НЕ_ПОМНЮ_ТОЧНО_STAMP*/ v(
 v.[START_SUM] + обороты
) in a.[ARC_MOVE] where rownum < 2 and v.date входит в период) :а это исходящий остаток


) in ::[AC_FIN]
;
Reddom
Участник со стажем


Вступление в Клуб: 25.01.2013
СообщениеЧт Июл 31, 2014 08:21    Ответить с цитатой
Полезность: Нет оценки
maestro пишет:

Я бы написал именно на аналитике Smile (ЦФТшной аналитике, на самом деле это агрегат)


Это не ЦФТшная аналитика - это аналитические функции, они рассмотрены в книге Том Кайта "Oracle для профессионалов. Книга 2 Расширение возможностей и защита".

А пример хорош.
vtar
Эксперт


Вступление в Клуб: 20.03.2009
СообщениеЧт Июл 31, 2014 08:24    Ответить с цитатой
Полезность: Нет оценки
Reddom пишет:

Это не ЦФТшная аналитика - это аналитические функции, они рассмотрены в книге Том Кайта "Oracle


Спасибо благородному дону, за то что просветил Maestro Smile
Я думаю, из этого поста он узнал много нового Smile))))
Reddom
Участник со стажем


Вступление в Клуб: 25.01.2013
СообщениеЧт Июл 31, 2014 08:37    Ответить с цитатой
Полезность: Нет оценки
Да, например, название книги Laughing

А вообще, посты читает не только Маестро, я надеюсь, и кому надо - тот возьмет на заметку.
devor
Профи


Вступление в Клуб: 13.02.2012
СообщениеПт Авг 01, 2014 11:54   Re: Список работающих счетов Ответить с цитатой
Полезность: 1
mike24 пишет:

Александр, спасибо! Слона-то я и не приметил Smile

Код:
select x(x%id : x_id
, abs(f.a_saldo_short(dat_ost+1, x, 'С', false )) : ost_out
, abs(f.a_saldo_short(dat_ost+1, x, 'С', true )) : ost_out_nt
, f.a_turn_short(dat_ost, dat_ost, x, true, false ) : turn_dt
, f.a_turn_short(dat_ost, dat_ost, x, false, false ) : turn_kt
, f.a_turn_short(dat_ost, dat_ost, x, true, true ) : turn_dt_nt
, f.a_turn_short(dat_ost, dat_ost, x, false, true ) : turn_kt_nt )
in ::[AC_FIN]
where exists (
   select rec(null) in ::[RECORDS] collections
   where rec%collection = x.[ARC_MOVE]
   and rec.[DATE] >= dat1 and rec.[DATE] <= dat2
   )

получился самый быстрый! Скорость приемлема.


1)В условие на дату добавь реквизит STAMP

Код:
where rec%collection = x.[ARC_MOVE]
   and rec.[DATE] >= dat1 and rec.[DATE] <= dat2
and rec.[STAMP]>=dat1

И будет работать быстрее за счет индекса.

2)Раздели селект по получению счетов и дальнейший расчет остатков - сначала надо счета вычитать во временную табличку, потом по ней считай остатки через f.a. Переключения между SQL и PL/SQL сильно замедляют расчет.
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle Часовой пояс: GMT + 3
Страница 1 из 1

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