Как правильно подсчитать количество уникальных документов в запросе 1С v7, если запрос обращается к табличным частям?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

При работе с запросами в 1С v7 программисты часто сталкиваются с ситуацией, когда необходимо получить итоговые данные по документам, содержащим табличные части. В частности, возникает потребность подсчитать количество уникальных документов, тогда как функция Счётчик() в запросе вместо документов выдает количество строк из этих табличных частей. Давайте подробно рассмотрим эту проблему и выясним, как ее эффективно решить.

Изначально, когда мы формируем запрос, который обращается к реквизитам табличной части документа (например, Документ.ЧекМагазины.Сумма или Документ.ЧекМагазины.СуммаСкидка), система 1С v7 воспринимает каждую строку табличной части как отдельную запись. Соответственно, если мы добавляем функцию Функция ВсегоДоков = Счётчик(Документ); (или просто Счётчик() без параметра), она подсчитывает не количество уникальных документов, а общее количество строк табличных частей, которые соответствуют условиям запроса. Это происходит потому, что 1С v7, фактически, "разворачивает" табличную часть документа, представляя ее как набор отдельных записей. Для решения этой задачи существуют несколько подходов, которые мы рассмотрим подробнее.


//{{ЗАПРОС(Продажи по чекам)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир         = Документ.ЧекМагазины.Кассир;
|СБП            = Документ.ЧекМагазины.ГУИДСБП;
|СуммаПродажи   = Документ.ЧекМагазины.Сумма;
|Скидка         = Документ.ЧекМагазины.СуммаСкидка;
|Группировка Кассир без групп;
|Условие (СокрЛП(СБП)<>Пусто);
|Функция ИтогСумма  = Сумма(СуммаПродажи);
|Функция ИтогСкидка = Сумма(Скидка);
|Функция ВсегоДоков = Счётчик(Документ); // Здесь возникает проблема: считает строки, а не документы
|"//}}ЗАПРОС

Решение 1: Использование отдельного запроса для подсчета документов

Один из самых надежных и понятных способов решения проблемы – это разделение задачи на два этапа. Сначала мы формируем отдельный запрос для подсчета количества уникальных документов, а затем выполняем основной запрос для получения агрегированных данных по строкам табличной части. После этого результаты двух запросов объединяем в коде 1С.

Шаг 1: Формируем запрос для подсчета уникальных документов

В этом запросе мы выбираем только ссылки на документы и группируем их, чтобы получить количество уникальных записей. Обратите внимание, что мы используем поле Документ.ЧекМагазины.ТекущийДокумент, которое представляет собой ссылку на сам документ. Группировка по этому полю позволит функции Счётчик() правильно подсчитать количество уникальных документов.


//{{ЗАПРОС(КоличествоДокументов)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|ДокСсылка = Документ.ЧекМагазины.ТекущийДокумент; // Получаем ссылку на сам документ
|Условие (СокрЛП(Документ.ЧекМагазины.ГУИДСБП)<>Пусто); // Используем то же условие, что и в основном запросе
|Группировка ДокСсылка; // Группируем по уникальному идентификатору документа
|Функция ВсегоДоков = Счётчик(); // Теперь это будет количество уникальных документов
|"//}}ЗАПРОС

Выполнение этого запроса вернет таблицу, где для каждого уникального документа будет одна строка с его ссылкой и значением ВсегоДоков равным 1 (если нет других группировок, или общее количество строк в документе, если без группировки по документу). Если же мы хотим получить общее количество документов, нам потребуется дополнительная обработка или агрегация этого результата.

Более эффективно будет выгрузить этот запрос в таблицу значений, где ключом будет ссылка на документ, а значением - количество документов (если нужно группировать по другим полям, например, по кассиру, это нужно будет делать уже в коде 1С, так как в этом запросе мы считаем *общие* документы).

Если мы хотим посчитать уникальные документы по каждому кассиру, как было в исходном запросе, мы можем модифицировать этот подход.


//{{ЗАПРОС(КоличествоДокументовПоКассирам)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир    = Документ.ЧекМагазины.Кассир;
|ДокСсылка = Документ.ЧекМагазины.ТекущийДокумент;
|Условие (СокрЛП(Документ.ЧекМагазины.ГУИДСБП)<>Пусто);
|Группировка Кассир;
|Группировка ДокСсылка; // Группируем по документу внутри каждой группы Кассира
|Функция Счетчик = 1; // Мы просто считаем наличие каждой уникальной связки Кассир-ДокСсылка
|"//}}ЗАПРОС

Этот запрос вернет таблицу с полями Кассир, ДокСсылка и Счетчик (равным 1). Затем в коде 1С мы можем пройти по этому результату, чтобы посчитать количество уникальных ДокСсылка для каждого Кассир.

Шаг 2: Формируем основной запрос для получения детальных данных

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


//{{ЗАПРОС(ПродажиПоЧекамДетализация)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир        = Документ.ЧекМагазины.Кассир;
|СБП           = Документ.ЧекМагазины.ГУИДСБП;
|СуммаПродажи  = Документ.ЧекМагазины.Сумма;
|Скидка        = Документ.ЧекМагазины.СуммаСкидка;
|Группировка Кассир без групп;
|Условие (СокрЛП(СБП)<>Пусто);
|Функция ИтогСумма  = Сумма(СуммаПродажи);
|Функция ИтогСкидка = Сумма(Скидка);
//"//}}ЗАПРОС

Этот запрос вернет агрегированные суммы продаж и скидок по каждому кассиру. Теперь у нас есть два набора данных: количество документов по кассирам и агрегированные суммы по кассирам. Нам остается объединить их.

Шаг 3: Объединение результатов в коде 1С

После выполнения обоих запросов, мы можем использовать объект ТаблицаЗначений для загрузки результатов и последующего объединения. Мы можем выполнить первый запрос (КоличествоДокументовПоКассирам) и загрузить его в ТаблицаЗначений. Затем пройти по этой таблице, подсчитывая уникальные документы по каждому кассиру, и сохранить эти данные. После этого выполняем второй запрос (ПродажиПоЧекамДетализация) и, также загрузив его в ТаблицаЗначений, добавляем к нему ранее полученные счетчики документов.


// Пример обработки в коде 1С
Перем Запрос;
Запрос = СоздатьОбъект("Запрос");

// --- Шаг 1: Получаем количество уникальных документов по кассирам ---
ТекстЗапросаДоков = "//{{ЗАПРОС(КоличествоДокументовПоКассирам)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир    = Документ.ЧекМагазины.Кассир;
|ДокСсылка = Документ.ЧекМагазины.ТекущийДокумент;
|Условие (СокрЛП(Документ.ЧекМагазины.ГУИДСБП)<>Пусто);
|Группировка Кассир;
|Группировка ДокСсылка;
|"//}}ЗАПРОС";

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

ТЗДокументы = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТЗДокументы);

// Теперь ТЗДокументы содержит уникальные связки Кассир-ДокСсылка.
// Нужно свернуть ее по Кассиру, чтобы получить количество документов на Кассира.
ТЗИтогиДокументов = СоздатьОбъект("ТаблицаЗначений");
ТЗИтогиДокументов.НоваяКолонка("Кассир");
ТЗИтогиДокументов.НоваяКолонка("ВсегоДоков", "Число", "5,0");

ПредыдущийКассир = "";
СчетчикДоков     = 0;

ТЗДокументы.ВыбратьСтроки();
Пока ТЗДокументы.ПолучитьСтроку() = 1 Цикл
    Если ТЗДокументы.Кассир <> ПредыдущийКассир Тогда
        Если ПредыдущийКассир <> "" Тогда
            НоваяСтрока = ТЗИтогиДокументов.НоваяСтрока();
            НоваяСтрока.Кассир    = ПредыдущийКассир;
            НоваяСтрока.ВсегоДоков = СчетчикДоков;
        КонецЕсли;
        ПредыдущийКассир = ТЗДокументы.Кассир;
        СчетчикДоков     = 0;
    КонецЕсли;
    СчетчикДоков = СчетчикДоков + 1;
КонецЦикла;

// Добавляем данные по последнему кассиру
Если ПредыдущийКассир <> "" Тогда
    НоваяСтрока = ТЗИтогиДокументов.НоваяСтрока();
    НоваяСтрока.Кассир    = ПредыдущийКассир;
    НоваяСтрока.ВсегоДоков = СчетчикДоков;
КонецЕсли;

// --- Шаг 2: Получаем агрегированные суммы продаж и скидок ---
ТекстЗапросаПродаж = "//{{ЗАПРОС(ПродажиПоЧекамДетализация)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир        = Документ.ЧекМагазины.Кассир;
|СБП           = Документ.ЧекМагазины.ГУИДСБП;
|СуммаПродажи  = Документ.ЧекМагазины.Сумма;
|Скидка        = Документ.ЧекМагазины.СуммаСкидка;
|Группировка Кассир без групп;
|Условие (СокрЛП(СБП)<>Пусто);
|Функция ИтогСумма  = Сумма(СуммаПродажи);
|Функция ИтогСкидка = Сумма(Скидка);
|"//}}ЗАПРОС";

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

ТЗИтогиПродаж = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТЗИтогиПродаж);

// --- Шаг 3: Объединяем результаты ---
// Теперь у нас есть две таблицы: ТЗИтогиДокументов (Кассир, ВсегоДоков)
// и ТЗИтогиПродаж (Кассир, ИтогСумма, ИтогСкидка).
// Мы можем объединить их, например, добавляя колонки из одной в другую.
ТЗИтогиПродаж.НоваяКолонка("ВсегоДоков", "Число", "5,0");

ТЗИтогиПродаж.ВыбратьСтроки();
Пока ТЗИтогиПродаж.ПолучитьСтроку() = 1 Цикл
    // Ищем соответствующего кассира в таблице документов
    НайденнаяСтрокаДоков = ТЗИтогиДокументов.НайтиЗначение(ТЗИтогиПродаж.Кассир, "Кассир");
    Если НайденнаяСтрокаДоков <> 0 Тогда
        ТЗИтогиДокументов.ПолучитьСтрокуПоНомеру(НайденнаяСтрокаДоков);
        ТЗИтогиПродаж.ВсегоДоков = ТЗИтогиДокументов.ВсегоДоков;
    Иначе
        ТЗИтогиПродаж.ВсегоДоков = 0; // Если кассир не найден в списке документов
    КонецЕсли;
КонецЦикла;

// Теперь ТЗИтогиПродаж содержит все необходимые данные.
// Можете вывести ее или использовать для дальнейших расчетов.

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

Решение 2: Многоуровневая группировка в запросе и постобработка

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

Предположим, мы хотим получить агрегированные суммы для каждого документа, а затем посчитать документы по кассирам. Мы можем сгруппировать запрос сначала по Кассир, а затем по Документ.ЧекМагазины.ТекущийДокумент. Это позволит нам просуммировать данные табличной части для каждого отдельного документа.


//{{ЗАПРОС(ПродажиПоКассирамСДетализациейДокументов)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир       = Документ.ЧекМагазины.Кассир;
|ДокСсылка    = Документ.ЧекМагазины.ТекущийДокумент;
|СуммаПродажи = Документ.ЧекМагазины.Сумма;
|Скидка       = Документ.ЧекМагазины.СуммаСкидка;
|Условие (СокрЛП(Документ.ЧекМагазины.ГУИДСБП)<>Пусто);
|Группировка Кассир;
|Группировка ДокСсылка; // Группируем по каждому документу в рамках кассира
|Функция ИтогСуммаДока  = Сумма(СуммаПродажи); // Сумма по документу
|Функция ИтогСкидкаДока = Сумма(Скидка);      // Скидка по документу
|"//}}ЗАПРОС

Выполнив этот запрос, мы получим результат, структурированный следующим образом:

  1. Кассир 1
  2. --- Документ 1 (с просуммированной ИтогСуммаДока и ИтогСкидкаДока)
  3. --- Документ 2 (с просуммированной ИтогСуммаДока и ИтогСкидкаДока)
  4. Кассир 2
  5. --- Документ 3 (с просуммированной ИтогСуммаДока и ИтогСкидкаДока)

Теперь в коде 1С нам останется пройтись по этому результату. При каждой смене Кассира мы начинаем новый подсчет документов и суммируем ИтогСуммаДока и ИтогСкидкаДока. При каждой строке мы увеличиваем счетчик документов. Таким образом, мы получаем необходимые агрегированные данные по каждому кассиру, включая количество уникальных документов.


// Пример обработки результата запроса с многоуровневой группировкой
Запрос.Текст = ТекстЗапросаСМногоуровневойГруппировкой; // Используем запрос выше
Если Запрос.Выполнить() = 0 Тогда
    Сообщить("Ошибка выполнения запроса!");
    Возврат;
КонецЕсли;

ТЗРезультат = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТЗРезультат);

ТЗИтоговая = СоздатьОбъект("ТаблицаЗначений");
ТЗИтоговая.НоваяКолонка("Кассир");
ТЗИтоговая.НоваяКолонка("ИтогСумма", "Число", "10,2");
ТЗИтоговая.НоваяКолонка("ИтогСкидка", "Число", "10,2");
ТЗИтоговая.НоваяКолонка("ВсегоДоков", "Число", "5,0");

ПредыдущийКассир = "";
ТекущийИтогСумма  = 0;
ТекущийИтогСкидка = 0;
ТекущийСчетчикДоков = 0;

ТЗРезультат.ВыбратьСтроки();
Пока ТЗРезультат.ПолучитьСтроку() = 1 Цикл
    Если ТЗРезультат.Кассир <> ПредыдущийКассир Тогда
        // Если кассир сменился, сохраняем предыдущие итоги
        Если ПредыдущийКассир <> "" Тогда
            НоваяСтрока = ТЗИтоговая.НоваяСтрока();
            НоваяСтрока.Кассир    = ПредыдущийКассир;
            НоваяСтрока.ИтогСумма = ТекущийИтогСумма;
            НоваяСтрока.ИтогСкидка = ТекущийИтогСкидка;
            НоваяСтрока.ВсегоДоков = ТекущийСчетчикДоков;
        КонецЕсли;
        // Начинаем новый расчет для текущего кассира
        ПредыдущийКассир = ТЗРезультат.Кассир;
        ТекущийИтогСумма  = 0;
        ТекущийИтогСкидка = 0;
        ТекущийСчетчикДоков = 0;
    КонецЕсли;

    // Суммируем данные по текущему документу и увеличиваем счетчик
    ТекущийИтогСумма  = ТекущийИтогСумма  + ТЗРезультат.ИтогСуммаДока;
    ТекущийИтогСкидка = ТекущийИтогСкидка + ТЗРезультат.ИтогСкидкаДока;
    ТекущийСчетчикДоков = ТекущийСчетчикДоков + 1;
КонецЦикла;

// Добавляем итоги для последнего кассира
Если ПредыдущийКассир <> "" Тогда
    НоваяСтрока = ТЗИтоговая.НоваяСтрока();
    НоваяСтрока.Кассир    = ПредыдущийКассир;
    НоваяСтрока.ИтогСумма = ТекущийИтогСумма;
    НоваяСтрока.ИтогСкидка = ТекущийИтогСкидка;
    НоваяСтрока.ВсегоДоков = ТекущийСчетчикДоков;
КонецЕсли;

// ТЗИтоговая содержит требуемые данные по кассирам.

Решение 3: Обработка результатов в "ТаблицеЗначений" с использованием метода "Свернуть()"

Этот подход является развитием предыдущих и наиболее гибким для сложных агрегаций. Мы можем выгрузить максимально детализированные данные из запроса в объект ТаблицаЗначений, а затем использовать встроенные методы ТаблицыЗначений, такие как Свернуть(), для выполнения агрегации и подсчета уникальных значений.

Шаг 1: Получаем все необходимые детали из запроса

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


//{{ЗАПРОС(ДетализацияДляТЗ)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир        = Документ.ЧекМагазины.Кассир;
|ДокСсылка     = Документ.ЧекМагазины.ТекущийДокумент;
|СуммаПродажи  = Документ.ЧекМагазины.Сумма;
|Скидка        = Документ.ЧекМагазины.СуммаСкидка;
|Условие (СокрЛП(Документ.ЧекМагазины.ГУИДСБП)<>Пусто);
|"//}}ЗАПРОС

Этот запрос вернет нам каждую строку табличной части, соответствующую условиям, вместе с информацией о кассире и ссылкой на документ.

Шаг 2: Обработка в коде 1С с использованием "ТаблицыЗначений"

После выполнения запроса мы загружаем результат в ТаблицаЗначений. Затем мы можем использовать метод Свернуть() для получения уникальных связок "Кассир-Документ" с агрегированными суммами по каждому документу, а затем для подсчета количества этих документов и общих сумм по кассирам.


// Пример обработки в коде 1С с использованием ТаблицыЗначений и Свернуть()
Запрос = СоздатьОбъект("Запрос");
Запрос.Текст = ТекстЗапросаДетализацииДляТЗ; // Используем запрос выше

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

ТЗИсходная = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТЗИсходная);

// Шаг 1: Агрегируем СуммаПродажи и Скидка по каждому уникальному документу для каждого кассира.
// Это даст нам одну строку для каждой связки Кассир-ДокСсылка,
// с итоговой суммой продажи и скидки по этому конкретному документу.
ТЗПоДокументам = СоздатьОбъект("ТаблицаЗначений");
ТЗИсходная.Копировать(ТЗПоДокументам); // Копируем исходные данные
ТЗПоДокументам.Свернуть("Кассир,ДокСсылка", "СуммаПродажи,Скидка");

// Теперь ТЗПоДокументам содержит: Кассир, ДокСсылка, СуммаПродажи (сумма по документу), Скидка (скидка по документу)

// Шаг 2: Агрегируем по Кассиру, чтобы подсчитать уникальные документы и общие суммы.
ТЗИтогиПоКассирам = СоздатьОбъект("ТаблицаЗначений");
ТЗИтогиПоКассирам.НоваяКолонка("Кассир");
ТЗИтогиПоКассирам.НоваяКолонка("ИтогСумма", "Число", "10,2");
ТЗИтогиПоКассирам.НоваяКолонка("ИтогСкидка", "Число", "10,2");
ТЗИтогиПоКассирам.НоваяКолонка("ВсегоДоков", "Число", "5,0");

ТЗПоДокументам.ВыбратьСтроки();
Пока ТЗПоДокументам.ПолучитьСтроку() = 1 Цикл
    // Ищем строку для текущего кассира в итоговой таблице
    НайденнаяСтрока = ТЗИтогиПоКассирам.НайтиЗначение(ТЗПоДокументам.Кассир, "Кассир");
    Если НайденнаяСтрока = 0 Тогда
        // Кассир еще не добавлен, создаем новую строку
        НоваяСтрока = ТЗИтогиПоКассирам.НоваяСтрока();
        НоваяСтрока.Кассир      = ТЗПоДокументам.Кассир;
        НоваяСтрока.ИтогСумма   = ТЗПоДокументам.СуммаПродажи;
        НоваяСтрова.ИтогСкидка  = ТЗПоДокументам.Скидка;
        НоваяСтрока.ВсегоДоков  = 1; // Первый документ для этого кассира
    Иначе
        // Кассир уже есть, обновляем данные
        ТЗИтогиПоКассирам.ПолучитьСтрокуПоНомеру(НайденнаяСтрока);
        ТЗИтогиПоКассирам.ИтогСумма   = ТЗИтогиПоКассирам.ИтогСумма + ТЗПоДокументам.СуммаПродажи;
        ТЗИтогиПоКассирам.ИтогСкидка  = ТЗИтогиПоКассирам.ИтогСкидка + ТЗПоДокументам.Скидка;
        ТЗИтогиПоКассирам.ВсегоДоков  = ТЗИтогиПоКассирам.ВсегоДоков + 1; // Увеличиваем счетчик документов
    КонецЕсли;
КонецЦикла;

// Теперь ТЗИтогиПоКассирам содержит агрегированные данные, включая количество документов,
// для каждого кассира.

Этот метод предоставляет большую гибкость в агрегации данных и подсчете уникальных значений по различным критериям уже после выполнения запроса, используя мощь объекта ТаблицаЗначений.

Решение 4: "Изподвыверты" с условной агрегацией `Сумма(1) Когда (НомерСтроки = 1)`

Существует также подход, который иногда называют "изподвывертом", позволяющий попытаться подсчитать документы непосредственно в запросе, если доступен номер строки табличной части. Идея состоит в том, чтобы присвоить значение "1" только первой строке каждого документа, а остальным – "0", и затем просуммировать эти единицы. Таким образом, сумма будет равна количеству документов.

Для этого мы могли бы попытаться использовать конструкцию Функция ВсегоДоков = Сумма(1) Когда (Документ.ЧекМагазины.НомерСтроки = 1);.


//{{ЗАПРОС(СУсловнымПодсчетомПервойСтроки)
|Период с ДатаНач по ДатаКон;
|ОбрабатыватьДокументы Проведенные;
|Кассир        = Документ.ЧекМагазины.Кассир;
|СБП           = Документ.ЧекМагазины.ГУИДСБП;
|СуммаПродажи  = Документ.ЧекМагазины.Сумма;
|Скидка        = Документ.ЧекМагазины.СуммаСкидка;
|Условие (СокрЛП(СБП)<>Пусто);
|Группировка Кассир без групп;
|Функция ИтогСумма  = Сумма(СуммаПродажи);
|Функция ИтогСкидка = Сумма(Скидка);
|Функция ВсегоДоков = Сумма(1) Когда (Документ.ЧекМагазины.НомерСтроки = 1); // Попытка подсчета документов
|"//}}ЗАПРОС

Важные ограничения и особенности этого подхода:

  1. Доступность `НомерСтроки`: Не всегда поле НомерСтроки табличной части документа доступно напрямую через "виртуальную таблицу" Документ.ЧекМагазины в запросах 1С v7. Обычно оно доступно при явном обращении к табличной части как к отдельной таблице (например, через вложенный запрос или соединение). В контексте синтаксиса, показанного в исходном сообщении, такое обращение может быть неочевидным или некорректным.
  2. Надежность: Этот подход может быть менее универсальным и потенциально ошибочным в различных сценариях. Например, если у документа нет табличных частей, или есть особенности в нумерации строк (хотя обычно НомерСтроки начинается с 1 и последовательно увеличивается).
  3. Производительность: Условные агрегатные функции могут быть менее производительными по сравнению с более прямыми методами (отдельный запрос или постобработка), особенно на больших объемах данных.

Мы рекомендуем использовать этот метод с осторожностью и только после тщательного тестирования, предпочитая более надежные подходы, такие как выполнение отдельных запросов или постобработка в ТаблицаЗначений, особенно если вам важна точность и стабильность работы отчета или обработки.

Заключение

Мы проанализировали ситуацию, когда функция Счётчик() в запросах 1С v7 подсчитывает строки табличной части вместо уникальных документов. Мы выяснили, что это стандартное поведение системы и для получения корректного количества документов необходимо использовать альтернативные подходы.

Наиболее надежными и часто используемыми методами являются:

  1. Разделение запроса на два: Один для подсчета документов, другой для агрегации данных, с последующим объединением результатов в коде 1С.
  2. Многоуровневая группировка: Использование группировки по документу для получения детализированных агрегатов, которые затем обрабатываются в коде.
  3. Обработка результатов в "ТаблицеЗначений": Выгрузка всех данных в ТаблицаЗначений и использование ее методов, таких как Свернуть(), для гибкой агрегации и подсчета.

Метод с условной агрегацией Сумма(1) Когда (НомерСтроки = 1) является более специфическим "изподвывертом", который может быть использован в определенных условиях, но требует более глубокого понимания внутренних механизмов работы запросов и потенциально менее надежен.

При выборе метода всегда следует учитывать объем данных, сложность требуемых агрегаций и требования к производительности. В большинстве случаев разделение запросов или постобработка в ТаблицаЗначений окажутся наиболее эффективными и понятными решениями.

← На главную