Подсчет количества элементов в списке иерархического справочника, при изменении отбора

07.10.15

База данных - Статистика базы данных

Допустим, у вас появилась хотелка: знать точное количество элементов справочника в группах (папках).
С чего начать? Конечно, запрос, но не простой! Будем использовать построитель запроса и, мало того, с ним будет использоваться динамический отбор!

Скачать файлы

Наименование Файл Версия Размер
Решение
.txt 4,71Kb
3
.txt 4,71Kb 3 Скачать

Что было:

А. База на платформе 8.3.5.1248 обычные формы.

Б. В базе список справочника "Номенклатура" иерархический.

Что нужно:

Подсчет количества элементов в списке справочника "Номенклатура", при изменении отбора.

Решение:

Для решения нам понадобится:

1. В список справочника "Номенклатура" добавить колонку "КоличествоЭлементов" (вы можете назвать её как вам нужно, но не забудьте потом изменить код).

2. Для элемента формы "Список" определить процедуру:

 

Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
    
    Для Каждого ОформлениеСтрок Из ОформленияСтрок Цикл
        Если ОформлениеСтрок.ДанныеСтроки.ЭтоГруппа Тогда
            ОформлениеСтрок.Ячейки.КоличествоЭлементов.Значение = ПолучитьКоличествоЭлементов(ОформлениеСтрок.ДанныеСтроки.Ссылка);   
        Иначе
            ОформлениеСтрок.Ячейки.КоличествоЭлементов.Значение = 1;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

3. Осталось посчитать в функции количество самих элементов:

 

Функция ПолучитьКоличествоЭлементов(ГруппаНоменклатуры)
    
    КоличествоЭлементов = 0;
        
    Построитель = Новый ПостроительЗапроса;
    Построитель.Текст =    "ВЫБРАТЬ
                           |    *
                           |ИЗ
                           |    Справочник.Номенклатура КАК Номенклатура
                           |ГДЕ
                           |    Номенклатура.ЭтоГруппа = ЛОЖЬ
                           |    И Номенклатура.Родитель = &ГруппаНоменклатуры";     
    Построитель.Параметры.Вставить("ГруппаНоменклатуры",ГруппаНоменклатуры);
    Построитель.ЗаполнитьНастройки();    
    
    //Установка отбора в построителе
    Для Каждого ЭлементОтбора Из Список.Отбор Цикл 
        Если ЭлементОтбора.Использование Тогда 
            
            Если Построитель.Отбор.Найти(ЭлементОтбора.ПутьКДанным) = Неопределено Тогда
                ЭлементОтбораВПостроителе               = Построитель.Отбор.Добавить(ЭлементОтбора.ПутьКДанным);
                ЭлементОтбораВПостроителе.ВидСравнения  = ЭлементОтбора.ВидСравнения;
                ЭлементОтбораВПостроителе.Значение      = ЭлементОтбора.Значение;
                ЭлементОтбораВПостроителе.ЗначениеС     = ЭлементОтбора.ЗначениеС; 
                ЭлементОтбораВПостроителе.ЗначениеПо    = ЭлементОтбора.ЗначениеПо;
                ЭлементОтбораВПостроителе.Использование = Истина;
            КонецЕсли
            
        КонецЕсли; 
    КонецЦикла;     
    
    //Получение результатов
    Построитель.Выполнить();
    Выборка = Построитель.Результат.Выбрать();

    КоличествоЭлементов = Выборка.Количество();      
    
    Возврат КоличествоЭлементов;
    
КонецФункции

Результат:

Код написали. Отбор работает. Результат производительности при открытии одно из папок: 0,360265.

Казалось бы, отлично, задача решена! Но это решение можно оптимизировать!

И сейчас я покажу, как улучшить результат в разы!

 

Решение2:

1. Без изменений.

2. Допишем условие, чтобы код работал только тогда, когда колонка "КоличествоЭлементоввидима:

 

Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
	
	ВидимостьКоличествоЭлементов = ЭлементыФормы.Список.Колонки.КоличествоЭлементов.Видимость;
	
	Для Каждого ОформлениеСтрок Из ОформленияСтрок Цикл
		Если ВидимостьКоличествоЭлементов Тогда
			Если ОформлениеСтрок.ДанныеСтроки.ЭтоГруппа Тогда
				ОформлениеСтрок.Ячейки.КоличествоЭлементов.Значение = ПолучитьКоличествоЭлементов(ОформлениеСтрок.ДанныеСтроки.Ссылка);	
			Иначе
				ОформлениеСтрок.Ячейки.КоличествоЭлементов.Значение = 1;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

3. Оптимизируем запрос, уменьшив количество обращений к базе (обратите внимание на условие в запросе и путь к данным для отбора):

 

Функция ПолучитьКоличествоЭлементов(ГруппаНоменклатуры)      
    
    КоличествоЭлементов = 0;
    
    Построитель = Новый ПостроительЗапроса;
    Построитель.Текст = "ВЫБРАТЬ
                        |    КОЛИЧЕСТВО(*) КАК Количество
                        |ИЗ
                        |    Справочник.Номенклатура КАК Номенклатура
                        |ГДЕ
                        |    Номенклатура.ЭтоГруппа = ЛОЖЬ
                        |    И Номенклатура.Родитель = &ГруппаНоменклатуры
                        |{ГДЕ
                        |    Номенклатура.Ссылка.*}";     
    Построитель.Параметры.Вставить("ГруппаНоменклатуры",ГруппаНоменклатуры);
    Построитель.ЗаполнитьНастройки();    
    
    //Установка отбора в построителе
    Для Каждого ЭлементОтбора Из Список.Отбор Цикл         
        Если ЭлементОтбора.Использование Тогда              
            Если Построитель.Отбор.Найти(ЭлементОтбора.ПутьКДанным) = Неопределено Тогда                 
                ЭлементОтбораВПостроителе               = Построитель.Отбор.Добавить("Ссылка." + ЭлементОтбора.ПутьКДанным);
                ЭлементОтбораВПостроителе.ВидСравнения  = ЭлементОтбора.ВидСравнения;
                ЭлементОтбораВПостроителе.Значение      = ЭлементОтбора.Значение;
                ЭлементОтбораВПостроителе.ЗначениеС     = ЭлементОтбора.ЗначениеС; 
                ЭлементОтбораВПостроителе.ЗначениеПо    = ЭлементОтбора.ЗначениеПо;
                ЭлементОтбораВПостроителе.Использование = Истина;                
            КонецЕсли                   
        КонецЕсли;          
    КонецЦикла;     
    
    //Получение результатов
    Построитель.Выполнить();
    
    Выборка = Построитель.Результат.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        КоличествоЭлементов  = Выборка.Количество;    
    КонецЦикла;
    
    Возврат КоличествоЭлементов;
    
КонецФункции

 

Результат2:

Теперь наш код стал оптимальнее. Отбор работает, как и должен. А вот результат производительности: 0,113300.

Нам удалось улучшить результат в разы, и это отлично! 

Задача решена на 100%!

Благодарности:

Исходный код был подсмотрен тут. В оптимизации решения помог Молодов Алексей!

Добавил текстовый файл с кодом двух решений! Всем удачи!

Практика программирования Задача

См. также

Физический размер таблиц (MSSQL)

Инструменты администратора БД Статистика базы данных Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Инструмент для получения физического размера таблиц ИБ (MSSQL)

1 стартмани

09.01.2024    1382    12    ImHunter    4    

7

Анализ документов: свертка базы, автотесты, динамика роста базы

Статистика базы данных Инструментарий разработчика Тестирование QA Платформа 1С v8.3 1С:Управление торговлей 10 1С:Управление производственным предприятием Абонемент ($m)

Внешняя обработка "Анализ документов и регистров" - можно использовать для детального изучения документов базы, связанных регистров (накопления и сведений). Предварительный анализ документов обычно требуется перед проведением свертки остатков базы, перед обновлением типовых релизов сильно измененной конфигурации, перед переходом на новую программу.

3 стартмани

29.12.2023    1106    9    RustIG    5    

7

Анализ использования номенклатуры

Статистика базы данных Логистика, склад и ТМЦ Платформа 1С v8.3 1С:ERP Управление предприятием 2 Абонемент ($m)

Очень часто хочется одним отчетом посмотреть, где и когда использовалась номенклатура. Вот это как раз такой отчет. Отчет полезен практически всем отделам предприятия. Им пользуются отделы закупки, продажи, склады, бухгалтеры.

1 стартмани

26.10.2023    718    12    dimanich70    0    

4

Сведения о присоединенных файлах

Статистика базы данных Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Внешний отчет для анализа данных присоединенных файлов за произвольный период в любой конфигурации.

2 стартмани

24.10.2023    1596    36    ixijixi    5    

19

История фоновых заданий

Журнал регистрации Статистика базы данных HighLoad оптимизация Конфигурации 1cv8 Абонемент ($m)

Удобный отчет по выполнению фоновых заданий в 1С с разбивкой по разным критериям, например по срокам, в какой последовательности, выполнение дольше всех, сколько одновременно и так далее.

5 стартмани

04.09.2023    796    6    Maxiko    0    

8

Количество документов в информационной базе в разрезе видов документов

Статистика базы данных Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Отчет выводит на экран количество документов в информационной базе. Это позволяет косвенно оценить объем данных в информационной базе. Данная информация может быть полезна, например, если предполагается свернуть информационную базу на определенную дату. От количества документов очень сильно зависит время свертки базы.

1 стартмани

16.08.2023    639    14    pwn    1    

3

Статистика по документам пользователя с версионированием по дате

Журнал регистрации Статистика базы данных Платформа 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 Россия Абонемент ($m)

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

5 стартмани

30.06.2023    1865    10    nemec    6    

5
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Serj1C 483 08.10.15 12:26 Сейчас в теме
> Казалось бы, отлично, задача решена! Но это решение можно оптимизировать!
Запрос в цикле - это ужасно.
Необходимо собрать все видимые группы, выполнить один запрос по этим группам и потом заполнять колонку.
2. Xershi 1474 08.10.15 13:29 Сейчас в теме
(1) Serj1C, поделитесь, как вы этот список будете получать?
3. gubanoff 63 06.11.15 14:32 Сейчас в теме
(2) заполняете массив, перебрав все строки в событии ПриПолученииДанных в цикле
Для Каждого ОформлениеСтрок Из ОформленияСтрок Цикл
. Потом этот массив передаете в функцию для подсчета. Потом еще раз проходите в цикле
Для Каждого ОформлениеСтрок Из ОформленияСтрок Цикл
и выводите значения. Сам запрос и его текст закешируйте в переменную и инициализируйте один раз при открытии. Построитель запроса тоже не надо, он потяжелее будет, чем просто запрос. Плюс все это дело можно делать, только если пользователь установил видимость колонки, т.к. это может быть не всем нужно. Не благодарите.
4. Xershi 1474 06.11.15 14:39 Сейчас в теме
(3) gubanoff, да уже давно подметил что "ОформленияСтрок" это обычная коллекция, которая и содержит нужный список.
Построитель запроса не просто так использовался, так что тут только ускорение получится на массиве. Видимость колонки и так в условии стоит, это вы похоже тоже пропустили.
Может сделаю 2 вариант уже с массивом. Правда пока вопрос не очень актуален.
5. Xershi 1474 02.12.15 10:20 Сейчас в теме
(3) gubanoff, провел исследование http://forum.infostart.ru/forum86/topic142222/. Результат поразил запрос не оптимален! И 43 (оптимальных) запроса выполняются быстрее 3(не оптимальных) при прочих равных условиях!
Оставьте свое сообщение