| Предыдущая тема :: Следующая тема   | 
	 
	
	
		| Автор | 
		Сообщение | 
	 
	
		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 сильно замедляют расчет. | 
			 
		  | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
  | 
   
 
		 |