Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
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
) |
|
Александр, спасибо! Слона-то я и не приметил
Код: | 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 с помощью аналитических функций... |
Вот. Вот тот человек, который всё время припиливает атомный двигатель к телеге!
Объясни мне, зачем?
Ну зачем здесь нужна эта неподъёмная блажь? |
Я бы написал именно на аналитике (ЦФТшной аналитике, на самом деле это агрегат)
Код: |
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 пишет: |
Я бы написал именно на аналитике (ЦФТшной аналитике, на самом деле это агрегат)
Код: |
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 минут на месячном интервале (разница в секунды).
Так что я склоняюсь к первому варианту как к более простому и понятному  |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Чт Июл 31, 2014 06:01   |
|
Полезность: Нет оценки
|
maestro пишет: | Random пишет: | Reddom пишет: | Если период произвольный и необходимо найти остатки и обороты, то лучше подсчитать в RECORDS с помощью аналитических функций... |
Вот. Вот тот человек, который всё время припиливает атомный двигатель к телеге!
Объясни мне, зачем?
Ну зачем здесь нужна эта неподъёмная блажь? |
Я бы написал именно на аналитике (ЦФТшной аналитике, на самом деле это агрегат)
Код: |
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 пишет: |
Я бы написал именно на аналитике (ЦФТшной аналитике, на самом деле это агрегат)
|
Это не ЦФТшная аналитика - это аналитические функции, они рассмотрены в книге Том Кайта "Oracle для профессионалов. Книга 2 Расширение возможностей и защита".
А пример хорош. |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Чт Июл 31, 2014 08:24   |
|
Полезность: Нет оценки
|
Reddom пишет: |
Это не ЦФТшная аналитика - это аналитические функции, они рассмотрены в книге Том Кайта "Oracle |
Спасибо благородному дону, за то что просветил Maestro
Я думаю, из этого поста он узнал много нового )))) |
|
 |
Reddom Участник со стажем
Вступление в Клуб: 25.01.2013
|
Чт Июл 31, 2014 08:37   |
|
Полезность: Нет оценки
|
Да, например, название книги
А вообще, посты читает не только Маестро, я надеюсь, и кому надо - тот возьмет на заметку. |
|
 |
devor Профи
Вступление в Клуб: 13.02.2012
|
Пт Авг 01, 2014 11:54  Re: Список работающих счетов |
|
Полезность: 1
|
mike24 пишет: |
Александр, спасибо! Слона-то я и не приметил
Код: | 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 сильно замедляют расчет. |
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|