Переключение на Главную Страницу Страницы: 1 [2]  ОтправитьПечать
Горячая тема (более 10 ответов) Группировка() (число прочтений - 6374 )
mrgreen
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 32
Зарегистрирован: 01. Августа 2009
Re: Группировка()
Ответ #15 - 06. Августа 2009 :: 14:29
Печать  
Потестировал на больших таблицах (по полсотни тысяч записей и более)... 70% времени уходит на поиск значения в таблице данных при выводе построчно и вцелом занимает времени  в 1,5 раз дольше чем обыкновенный запрос с группировками

ээээх

чтоб не искать по таблице меня может спасти аналог "все вошедшиеВЗапрос" по группировке "Склад"... такое можно организовать (внешними соединенинями попадёт весь справочник а мне только те которые когда-либо появлялись в итогах и движениях) ?
  
Наверх
 
IP записан
 
alexdd
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 347
Зарегистрирован: 25. Июня 2007
Re: Группировка()
Ответ #16 - 06. Августа 2009 :: 14:35
Печать  
это типа тот вариант, что я предалагал? там поиск данных(запрос) не построчно, а для группировки. Индексы на таблицу вешал?
  
Наверх
 
IP записан
 
mrgreen
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 32
Зарегистрирован: 01. Августа 2009
Re: Группировка()
Ответ #17 - 06. Августа 2009 :: 14:41
Печать  
да... он самый и поиск по индексу запросом сформированным из ИД Номенклатуры Размера и Склада

поиск стандартом тб.НайтиЗначение() потом позиционируемся на строку и вытягиваем оттуда данные (можно без позиционирования не суть важно там задержки минимальны)
  
Наверх
 
IP записан
 
alexdd
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 347
Зарегистрирован: 25. Июня 2007
Re: Группировка()
Ответ #18 - 06. Августа 2009 :: 15:08
Печать  
та ну не верю, ну вот, например, код. Код нерабочий, просто как пример
Код
Выбрать все
Перем СписокГруппировок;
Перем RS;
//=====================================
Процедура ВывестиГруппировку(Номер, спОтбор = 0)
	ИмяГруппировки = СписокГруппировок.ПолучитьЗначение(Номер);

	стрКолонки     = "";
	стрКолонкиСумм = "";

	Если ИмяГруппировки = "Склад" Тогда
		стрКолонки = стрКолонки + "Склад  $Справочник.Склады,"
	ИначеЕсли ИмяГруппировки = "ТМЦ" Тогда
		стрКолонки = стрКолонки + "ТМЦ  $Справочник.ТМЦ,"
	КонецЕсли;

	стрКолонки = стрКолонки + "
	|sum(Сумма) Сумма";


	стрУсловие = "";

	Если ТипЗначенияСтр(спОтбор) = "СписокЗначений" Тогда

		Для инд = 1 По спОтбор.РазмерСписка() Цикл

			стр = "";
			зн  = спОтбор.ПолучитьЗначение(инд,стр);

			Если зн = "" Тогда
				Продолжить;
			КонецЕсли;

			стрУсловие = стрУсловие + стр + " = '" + Метадата.ЗначениеВСтрокуБД(зн) + "' and " ;//Метадата - MetaDataWork

		КонецЦикла;

		стрУсловие = "
		|where " + Сред(стрУсловие,1,СтрДлина(стрУсловие) - 4);
	КонецЕсли;

	ТекстЗапроса = "
	|set nocount on
	|select
	|"+стрКолонки + "
	|from
	|  #tmp  
	|"+стрУсловие+"
	|group by
	| "+ИмяГруппировки+"
	|";


	Попытка
		тз = RS.ВыполнитьИнструкцию(ТекстЗапроса);
	Исключение                                  
		Сообщить(RS.ПолучитьОписаниеОшибки(),"!!!");
		Возврат;
	КонецПопытки;

	тз.ВыбратьСтроки();

	Пока тз.ПолучитьСтроку() = 1 Цикл

		текОбъект = тз.ПолучитьЗначение(тз.НомерСтроки,ИмяГруппировки);


		Если Номер = 1 Тогда
			спОтбор = СоздатьОбъект("СписокЗначений");

			спОтбор.Установить(ИмяГруппировки,текОбъект);
		Иначе
			Для инд = Номер По СписокГруппировок.РазмерСписка() Цикл
				зн = СписокГруппировок.ПолучитьЗначение(инд);

				спОтбор.Установить(зн,"");

			КонецЦикла;
		КонецЕсли;

		спОтбор.Установить(ИмяГруппировки,текОбъект);

		//здесь выводим строки в Таблицу
		ПечОбъект = текОбъект;
		ПечСумма  = тз.Сумма;
		//и т.п.

		Если Номер < СписокГруппировок.РазмерСписка() Тогда

			ВывестиГруппировку(Номер + 1,спОтбор);
		КонецЕсли;

	КонецЦикла;
КонецПроцедуры
//=====================================
Процедура Сформировать()

	СписокГруппировок = СоздатьОбъект("СписокЗначений");
	СписокГруппировок.ДобавитьЗначение("Склад");
	СписокГруппировок.ДобавитьЗначение("ТМЦ");

	RS = СоздатьОбъект("ODBCRecordSet");
	RS.УстБД1С();

	ТекстЗапроса = "
	|if object_id('tempdb..#tmp') is not null
	| drop table #tmp
	|
	|create table #tmp(Склад char(9) not null, ТМЦ char(9) not null, Сумма numeric(11,2) not null)";

	рез = RS.Выполнить(ТекстЗапроса);
	Если рез = 0 Тогда
		Сообщить(RS.ПолучитьОписаниеОшибки(););
		Возврат;
	КонецЕсли;

	ТекстЗапроса = "
	|set nocount on
	|insert into #tmp
	|select
	|  Склад,
	|  ТМЦ,
	|  sum(Сумма) Сумма
	|from
	|  <.....>
	|where
	|  <.....>
	|";

	ТекстЗапроса = "
	|create index indx_Склад on #tmp(Склад)
	|create index indx_ТМЦ on #tmp(ТМЦ)
	|create index indx_СкладТМЦ on #tmp(Склад,ТМЦ)
	|";

	рез = RS.Выполнить(ТекстЗапроса);
	Если рез = 0 Тогда
		Сообщить(RS.ПолучитьОписаниеОшибки(););
		Возврат;
	КонецЕсли;

	ВывестиГруппировку(1);

		   //тут открываем таблицу
КонецПроцедуры
 

  
Наверх
 
IP записан
 
alexdd
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 347
Зарегистрирован: 25. Июня 2007
Re: Группировка()
Ответ #19 - 06. Августа 2009 :: 15:10
Печать  
зы: пропустил там Выполение запроса одно, но принцип понятенУлыбка
  
Наверх
 
IP записан
 
mrgreen
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 32
Зарегистрирован: 01. Августа 2009
Re: Группировка()
Ответ #20 - 06. Августа 2009 :: 15:17
Печать  
угу... ты получается создаешь таблицы для поиска на сервере и потом из них выдергиваешь необходимое а я на клиенте и там уже поиск средствами самой 1це Печаль

этож сколько действий надо... если ничего не придумаю  то так попробуем поступить
  
Наверх
 
IP записан
 
alexdd
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 347
Зарегистрирован: 25. Июня 2007
Re: Группировка()
Ответ #21 - 06. Августа 2009 :: 15:20
Печать  
mrgreen писал(а) 06. Августа 2009 :: 15:17:
угу... ты получается создаешь таблицы для поиска на сервере и потом из них выдергиваешь необходимое а я на клиенте и там уже поиск средствами самой 1це Печаль

ну так я ж об этом с самого начала и говорилУлыбка
  
Наверх
 
IP записан
 
classic
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 330
Местоположение: г. Харьков
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Группировка()
Ответ #22 - 06. Августа 2009 :: 18:39
Печать  
А я делаю так: выдергиваю с сервера одним запросом все, что нужно пользователю показать. Как правило, запрос генерируется в зависимости от натыканных пользователем галочек и прочего.

Полученную ТЗ перебираю и вношу в таблицу, формат которой точно совпадает с выводом (создаю доп. колонки для горизонтальных разворотов, заполняю данными). После чего эту таблицу сворачиваю, сортирую и при помощи класса Отчет.ИтогиПоГруппировкам вываливаю на печать. Получается быстро и наглядно, и код легкочитаемый и легко модифицируемый получается.
  
Наверх
 
IP записан
 
mrgreen
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 32
Зарегистрирован: 01. Августа 2009
Re: Группировка()
Ответ #23 - 07. Августа 2009 :: 12:21
Печать  
мдя... и таблицу креатить не быстро и разбирать на кленте полученную тоже не быстро

пока пытаюсь разобраться с олап сделал следующее

Код
Выбрать все
	Для поз=1 По спВыбСклИД.РазмерСписка() Цикл
		ТекстЗапроса = ТекстЗапроса + "
		|			SUM(CASE WHEN ((ВидД = 105) OR (ВидД = 52) OR (ВидД = 3737)) AND (_Склад='"+спВыбСклИД.ПолучитьЗначение(поз)+"') THEN _Приход ELSE 0 END) AS КвоПрих_"+спВыбСклК.ПолучитьЗначение(поз)+", -- приход (если Вид док = 'Приход' или 'ВводОстатков' или 'Перемещение')
		|			SUM(CASE WHEN ((ВидД = 443) OR (ВидД = 3737))AND (_Склад='"+спВыбСклИД.ПолучитьЗначение(поз)+"') THEN _Расход ELSE 0 END) AS КвоСпис_"+спВыбСклК.ПолучитьЗначение(поз)+", -- списание (если Вид док = 'Списание' или 'Перемещение')
		|			SUM(CASE WHEN (ВидД = 3767) AND (_Склад='"+спВыбСклИД.ПолучитьЗначение(поз)+"') THEN _Расход ELSE 0 END) AS КвоПрод_"+спВыбСклК.ПолучитьЗначение(поз)+", -- продажа (если Вид док = 'Продажа')
		|			SUM(CASE WHEN _Склад='"+спВыбСклИД.ПолучитьЗначение(поз)+"' THEN _НачОст+_Приход-_Расход ELSE 0 END) AS КвоОст_"+спВыбСклК.ПолучитьЗначение(поз)+",";
	КонецЦикла; 



т.е. расчитываю данные для по движениям/остаткам для каждого из складов фильтра в оттельные поля и затем при выводе по коду колонки их и вывожу

Код
Выбрать все
		Для поз = 1 По спВыбСклК.РазмерСписка() Цикл
			печТочка = спВыбСклК.получитьЗначение(поз);
			пПрих = тз.ПолучитьЗначение(сч,"квоПрих_"+печТочка);
			пСпис = тз.ПолучитьЗначение(сч,"квоСпис_"+печТочка);
			пПрод = тз.ПолучитьЗначение(сч,"квоПрод_"+печТочка);
			пОст  = тз.ПолучитьЗначение(сч,"квоОст_"+печТочка);
			пИтОст = тз.ПолучитьЗначение(сч,"квоОст_"+печТочка);
			Таб.ПрисоединитьСекцию("Строка|Ост");

		КонецЦикла; 



понимаю что решение больше 1це шное нежели оптимально но так работает и по результатам за 5 дней по паре десятков складов ускорение в 3 раза ны выходе и чем больше период и кол-во складов тем разница ощутимее (растет не линейно)
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1 [2] 
ОтправитьПечать