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


I Love YaBB 2!

Сообщений: 30
Зарегистрирован: 04. Сентября 2006
Эффективное получение итогов по группам спр. в SQL
06. Октября 2006 :: 08:50
Печать  
Хотелось бы чтобы SQL запрос посчитал итоги по группам справочника. Ничего стоящего я пока не нашел. Предлагаю высказывать свой мысли в этом топе.
Вот моя идея:
Код
Выбрать все
SELECT
	SUM(Данные.ОстатокТовараПриход) as ОстатокТовараПриход,
	Данные.ТоварУровень5 as ТоварУровень5,
	Данные.ТоварУровень4 as ТоварУровень4,
	Данные.ТоварУровень3 as ТоварУровень3,
	Данные.ТоварУровень2 as ТоварУровень2,
	Данные.ТоварУровень1 as ТоварУровень1,
	Данные.Товар as Товар,
	6 - GROUPING(Данные.ТоварУровень5) - GROUPING(Данные.ТоварУровень4) - GROUPING(Данные.ТоварУровень3) - GROUPING(Данные.ТоварУровень2) - GROUPING(Данные.ТоварУровень1) - GROUPING(Данные.Товар) as УровеньИтогов
FROM	(
	SELECT
		CASE DEBKRED WHEN 0 THEN RA.SP16023 ELSE 0 END as ОстатокТовараПриход,
		СпрНоменклатураУровень4.PARENTID as ТоварУровень5,
		СпрНоменклатураУровень3.PARENTID as ТоварУровень4,
		СпрНоменклатураУровень2.PARENTID as ТоварУровень3,
		СпрНоменклатураУровень1.PARENTID as ТоварУровень2,
		СпрНоменклатура.PARENTID as ТоварУровень1,
		RA.SP16021 as Товар
	FROM
		RA16019 as RA(NOLOCK)
	LEFT JOIN
		_1SJOURN as J(NOLOCK) ON RA.IDDOC = J.IDDOC
	LEFT JOIN
		sc156 as СпрНоменклатура ON СпрНоменклатура.ID = RA.SP16021
	LEFT JOIN
		sc156 as СпрНоменклатураУровень1 ON СпрНоменклатураУровень1.ID = СпрНоменклатура.PARENTID
	LEFT JOIN
		sc156 as СпрНоменклатураУровень2 ON СпрНоменклатураУровень2.ID = СпрНоменклатураУровень1.PARENTID
	LEFT JOIN
		sc156 as СпрНоменклатураУровень3 ON СпрНоменклатураУровень3.ID = СпрНоменклатураУровень2.PARENTID
	LEFT JOIN
		sc156 as СпрНоменклатураУровень4 ON СпрНоменклатураУровень4.ID = СпрНоменклатураУровень3.PARENTID
	LEFT JOIN
		sc156 as СпрНоменклатураУровень5 ON СпрНоменклатураУровень5.ID = СпрНоменклатураУровень4.PARENTID
	WHERE
		J.DATE_TIME_IDDOC >= '20060101     0     0   ' AND
		J.DATE_TIME_IDDOC <  '20060201     0     0   '
	) as Данные
GROUP BY
	Данные.ТоварУровень5,
	Данные.ТоварУровень4,
	Данные.ТоварУровень3,
	Данные.ТоварУровень2,
	Данные.ТоварУровень1,
	Данные.Товар
WITH ROLLUP
ORDER BY
	Данные.ТоварУровень5,
	Данные.ТоварУровень4,
	Данные.ТоварУровень3,
	Данные.ТоварУровень2,
	Данные.ТоварУровень1,
	Данные.Товар,
	УровеньИтогов 



Внутренний запрос получает данные из регистра, внешний группирует с подсчетом итогов по группам.
  
Наверх
 
IP записан
 
Valar
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 30
Зарегистрирован: 04. Сентября 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #1 - 10. Октября 2006 :: 10:16
Печать  
Неужели никому нечего сказать по этому поводу…  Озадачен
  
Наверх
 
IP записан
 
zyris
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 12
Зарегистрирован: 05. Сентября 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #2 - 16. Октября 2006 :: 03:39
Печать  
Тоже пытаюсь сделать нечто подобное перебрал кучу вариантов по построению дерева, но все они оказываются медленее средствами 1с. Пиши на zyris@mail.ru или стучи в асю 301656920 интересно пообщаться на эту тему.
  
Наверх
 
IP записан
 
dip
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 37
Зарегистрирован: 19. Мая 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #3 - 16. Октября 2006 :: 11:05
Печать  
Я просто выгружаю результат запроса в Индексированную таблицу а потом "Группировать"
  
Наверх
 
IP записан
 
steban
1c++ developer
Отсутствует


#define sizeof(x) rand()

Сообщений: 787
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Эффективное получение итогов по группам спр. в
Ответ #4 - 16. Октября 2006 :: 11:25
Печать  
Для запросов с большими объемами выборки я использую OLAP и несбалансированные иерархии (для получения итогов по группам).
Примерно как тут: Сводный отчет по реализации для ТиС на базе MSOLAP.
Для небольших отчетов использую класс ТаблицаГруппировок.
Все никак не соберусь переписать для класса ИндексированнаяТаблица.
  

int getRandomNumber()&&{&&  return 4; //chosen by fair dice roll&&         //guaranteed to be random&&}
Наверх
 
IP записан
 
zyris
YaBB Newbies
*
Отсутствует


I Love YaBB 2!

Сообщений: 12
Зарегистрирован: 05. Сентября 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #5 - 18. Октября 2006 :: 06:36
Печать  
Так отчет на проклубе только для зарегистрированных пользователей. Кто может может выложить куда-нибудь в другое место?
  
Наверх
 
IP записан
 
steban
1c++ developer
Отсутствует


#define sizeof(x) rand()

Сообщений: 787
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Эффективное получение итогов по группам спр. в
Ответ #6 - 18. Октября 2006 :: 07:12
Печать  
  

int getRandomNumber()&&{&&  return 4; //chosen by fair dice roll&&         //guaranteed to be random&&}
Наверх
 
IP записан
 
Valar
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 30
Зарегистрирован: 04. Сентября 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #7 - 18. Октября 2006 :: 16:30
Печать  
Сейчас разбираюсь как итоги по группам считаются в компоненте «ToySQL». Получается довольно таки быстро. У меня в базе в справочнике "Номенклатура" около 17000 элементов, с уровнем вложенности до 10. В таблице с итогами по регистру "Остатки товаров" около 730000 записей. Вся база около 10Гб. Так вот, скрипт, рассчитывающий итоги по двум измерениям + итоги по группам по одному из измерений выполнялся всего 2 секунды, вернул 15000 записей. Пример скрипта во вложении.
  

example_001.zip ( 1 KB | Загрузки )
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Эффективное получение итогов по группам спр. в
Ответ #8 - 22. Октября 2006 :: 12:15
Печать  
Valar писал(а) 18. Октября 2006 :: 16:30:
Сейчас разбираюсь как итоги по группам считаются в компоненте «ToySQL». Получается довольно таки быстро.


Переписал по этому примеру один отчет у себя в ДБФ. Раньше был запрос + ИТ.Загрузить + ИТ.Группировать. Новый алгоритм данные подготавливает в 2 раза быстрее. Хотя кода получилось просто огромное количество Улыбка Думаю, такой метод вполне имеет право на жизнь.
Тестировалось на справочнике с 1000 товаров.
  
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Эффективное получение итогов по группам спр. в
Ответ #9 - 23. Октября 2006 :: 06:00
Печать  
А нет ли желающих попробовать методу подсчёта итогов по группам с помощью ИТ, но без Группировать()?  Оно однозначно (и намного) быстрее чем Группировать, но пока ни разу не приходилось сравнивать с подсчётом итогов по группам в запросе. Было бы здорово получить статистику, да ещё и на халяву  Улыбка

Код
Выбрать все
	ИмяСправочника = "Контрагенты";

	РС = СоздатьОбъект("ODBCRecordSet");

	//Основной запрос с данными. Включаются только элементы и их непосредственные родители
	ТекстЗапроса = "
	|SELECT
	|	ID Эл,
	|	ParentID Родитель,
	|	1 Сумма
	|FROM
	|	$Справочник."+ИмяСправочника+"
	|WHERE IsFolder = 2
	|";
	итЭлементы = СоздатьОбъект("ИндексированнаяТаблица");
	РС.ВыполнитьИнструкцию(ТекстЗапроса, итЭлементы);


	КоличествоСтрок = итЭлементы.КоличествоСтрок();
	Старт = _GetPerformanceCounter();

	//собираем все группы, какие есть в справочнике
	ТекстЗапроса = "
	|SELECT
	|	ID Группа,
	|	ParentID Родитель,
	|	0 Сумма
	|FROM
	|	$Справочник."+ИмяСправочника+"
	|WHERE IsFolder = 1
	|";
	итГруппы = СоздатьОбъект("ИндексированнаяТаблица");
	РС.ВыполнитьИнструкцию(ТекстЗапроса, итГруппы);
	итГруппы.ДобавитьИндекс("Группа", "Группа");

	//Топаем по элементам, и одновременно подсчитываем итоги по группам
	итЭлементы.ВыбратьСтроки();
	Пока итЭлементы.ПолучитьСтроку() = 1 Цикл
		Сумма = итЭлементы.Сумма;
		Группа = итЭлементы.Родитель;
		Пока итГруппы.НайтиСтроку("Группа", Группа, 0, 1) > 0 Цикл
			итГруппы.Сумма = итГруппы.Сумма + Сумма;
			Группа = итГруппы.Родитель;
		КонецЦикла;
	КонецЦикла;
	Стоп = _GetPerformanceCounter();
	Сообщить(""+ КоличествоСтрок+" - "+ (Стоп-Старт));
 

  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #10 - 23. Октября 2006 :: 06:05
Печать  
Ха, назад в будущее Улыбка

Мы же с этого начинали год назад, когда думали о плоских таблицах для группировки.
Думаешь, будет быстрее, даже на SQL?

Даже эта идея с доп. таблицами родителей была, но была отложена как непомерно сложная для конечного программиста Улыбка
Но на сегодняшний день я ее поддерживаю.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #11 - 23. Октября 2006 :: 06:08
Печать  
+

Твоя реализация - очень быстрая, это безусловно.
У меня такие же работают и проблем не знаю.

Но когда начнешь решать вопрос упорядочивания вывода, вот тут будут тормоза на заполнении колонок представлений и построении многомерного индекса.

Еще +
На самом деле, ИТ отлично это все потянет, только надо разработать формат данных, которые ей требуются для эффективного построения этого многомерного индекса:
- ID, parentID, представление_для сортировки, колонка_суммы - это для элементов
- ID, parentID, представление_для сортировки - это для групп

В итоге и получим простую плоскую таблицу группировок.
  

De quelle planète es-tu?
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Эффективное получение итогов по группам спр. в
Ответ #12 - 23. Октября 2006 :: 06:16
Печать  
kms писал(а) 23. Октября 2006 :: 06:05:
Ха, назад в будущее Улыбка

Мы же с этого начинали год назад, когда думали о плоских таблицах для группировки.
Думаешь, будет быстрее, даже на SQL?

Даже эта идея с доп. таблицами родителей была, но была отложена как непомерно сложная для конечного программиста Улыбка
Но на сегодняшний день я ее поддерживаю.

Вот я как раз не знаю, будет ли это быстрее, чем на SQL. Но по сравнению с ИТ::Группировать() - совершенно однозначно быстрее. По двум причинам: 1) индекс строится 1 раз, 2) все итоги считаются в 1 проход.
Причём, приведённый код неоптимален, от второго вложенного цикла надо избаляться.  У меня сейчас во многих отчётах используется примерно такая же метода для получения итогов по группировкам, одновременно с выводом печатной формы (т.е. всё делается за 1 проход по таблице с данными из запроса). По времени занимает примерно столько же, сколько и вывод секций в печ. форму.  Может, прямо в запросе итоги считать и быстрее, но на порядок больше гемору.
  
Наверх
 
IP записан
 
kms
1c++ power user
1c++ moderator
Отсутствует


я хочу, чтоб сюда проложили
дорогу оттуда...

Сообщений: 4632
Зарегистрирован: 19. Мая 2006
Re: Эффективное получение итогов по группам спр. в
Ответ #13 - 23. Октября 2006 :: 06:17
Печать  
ADirks писал(а) 23. Октября 2006 :: 06:16:
Может, прямо в запросе итоги считать и быстрее, но на порядок больше гемору.

Отож Улыбка

И, кстати, нагрузка распределяется по-другому.
Как ни странно, я становлюсь сторонником распределенных вычислений (на современной-то технике).
  

De quelle planète es-tu?
Наверх
 
IP записан
 
ADirks
1c++ developer
1c++ moderator
Отсутствует


А нужны ли мы нам?

Сообщений: 692
Местоположение: Новосибирск
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Эффективное получение итогов по группам спр. в
Ответ #14 - 23. Октября 2006 :: 06:19
Печать  
Цитата:
Но когда начнешь решать вопрос упорядочивания вывода, вот тут будут тормоза на заполнении колонок представлений и построении многомерного индекса.
А у меня исходная таблица сортируется всегда в самом запросе, и все нужные представления и расшифровки тоже в запросе формируются. При выводе на печать я в базу уже не лезу.
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 
ОтправитьПечать