В практике разработки на платформе 1С часто возникают задачи, когда необходимо извлечь статистические данные на основе строковых идентификаторов. Типичный пример — определение пола сотрудника по его Персональному идентификационному номеру (ПИН/ИНН). В некоторых странах, например в Кыргызстане, первая цифра ИНН жестко закреплена за полом: «1» — для женщин, «2» — для мужчин. Рассмотрим подробно, как реализовать выборку таких данных, правильно настроить фильтрацию в запросе и эффективно подсчитать количество сотрудников.
Самый простой и эффективный способ найти строки, начинающиеся с определенного символа, — использовать оператор ПОДОБНО. Этот оператор позволяет использовать маски поиска. Символ % в маске означает любую последовательность произвольных символов.
Проанализируем ситуацию: если нам нужно найти всех сотрудников-женщин, чей ИНН начинается с единицы, текст запроса будет выглядеть следующим образом:
ВЫБРАТЬ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СведенияОСотрудникахСрезПоследних.Сотрудник) КАК КоличествоЖенщин
ИЗ
РегистрСведений.СведенияОСотрудниках.СрезПоследних(&Период, ) КАК СведенияОСотрудникахСрезПоследних
ГДЕ
СведенияОСотрудникахСрезПоследних.Сотрудник.ИНН ПОДОБНО "1%"
И НЕ СведенияОСотрудникахСрезПоследних.Прекращен
Разберем этот код по шагам:
Если по каким-то причинам использование оператора ПОДОБНО неудобно (например, при сложной логике анализа нескольких символов), можно воспользоваться функцией ПОДСТРОКА. Она выделяет часть строки заданной длины, начиная с указанной позиции.
Рассмотрим пример реализации:
ВЫБРАТЬ
КОЛИЧЕСТВО(Сведения.Сотрудник) КАК Количество
ИЗ
РегистрСведений.СведенияОСотрудниках.СрезПоследних КАК Сведения
ГДЕ
ПОДСТРОКА(Сведения.Сотрудник.ИНН, 1, 1) = "1"
В данном случае ПОДСТРОКА(ИНН, 1, 1) берет первый символ строки. Однако стоит помнить, что использование функций внутри секции ГДЕ может замедлить выполнение запроса на очень больших объемах данных, так как СУБД не всегда может эффективно использовать индексы в таких случаях. Оператор ПОДОБНО для поиска по началу строки обычно работает быстрее.
Часто требуется получить не просто количество женщин, а сводный отчет: сколько в базе мужчин, сколько женщин и общее количество. Вместо выполнения нескольких запросов в цикле, выясним, как сделать это за один проход к базе данных с помощью конструкции ВЫБОР.
Посмотрим на пример такого запроса:
ВЫБРАТЬ
СУММА(ВЫБОР
КОГДА Сведения.Сотрудник.ИНН ПОДОБНО "1%"
ТОГДА 1
ИНАЧЕ 0
КОНЕЦ) КАК КоличествоЖенщин,
СУММА(ВЫБОР
КОГДА Сведения.Сотрудник.ИНН ПОДОБНО "2%"
ТОГДА 1
ИНАЧЕ 0
КОНЕЦ) КАК КоличествоМужчин,
КОЛИЧЕСТВО(Сведения.Сотрудник) КАК ВсегоСотрудников
ИЗ
РегистрСведений.СведенияОСотрудниках.СрезПоследних(&Период, Прекращен = ЛОЖЬ) КАК Сведения
Этот подход крайне эффективен. Мы используем функцию СУММА в сочетании с условным оператором. Если условие выполняется, система прибавляет «1», если нет — «0». В итоге мы получаем готовую таблицу с результатами в одной строке.
Важным моментом при работе с регистром сведений является производительность. В исходном вопросе условие НЕ Прекращен было вынесено в секцию ГДЕ. Это распространенная ошибка. Выясним, почему лучше использовать параметры виртуальной таблицы.
Когда вы пишете условие в ГДЕ, система сначала выбирает все записи из базы, а потом отсеивает ненужные. Если же вы поместите условие в параметры СрезПоследних, фильтрация произойдет на этапе формирования временной таблицы на сервере СУБД.
Правильный вариант фильтрации активных сотрудников:
РегистрСведений.СведенияОСотрудниках.СрезПоследних(&Период, Прекращен = ЛОЖЬ)
После того как запрос написан, нам нужно вывести результат в отчет или экранную форму. Разберем, как правильно получить данные из выборки:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
// Заполняем параметры области макета
ОбластьМакета.Параметры.СотрудникиЖенщины = Выборка.КоличествоЖенщин;
ОбластьМакета.Параметры.Всего = Выборка.ВсегоСотрудников;
КонецЕсли;
Важный нюанс: Если ваш запрос содержит группировку или агрегатные функции (как в примерах выше) без секции СГРУППИРОВАТЬ ПО, он всегда вернет одну строку, даже если данных нет (в этом случае в полях будут нули или NULL). Поэтому проверка Выборка.Следующий() обязательна.
Хотя анализ ИНН позволяет быстро решить задачу, полагаться только на него в долгосрочной перспективе рискованно. Рекомендуется:
Сотрудники явный реквизит Пол с типом ПеречислениеСсылка.Пол.Пол, что сделает код более понятным для других разработчиков и исключит ошибки при работе с иностранными гражданами, у которых структура ИНН может быть иной.Для реализации группировки по уже существующему реквизиту запрос будет выглядеть так:
ВЫБРАТЬ
Сотрудники.Пол КАК Пол,
КОЛИЧЕСТВО(Сотрудники.Ссылка) КАК Количество
ИЗ
Справочник.Сотрудники КАК Сотрудники
СГРУППИРОВАТЬ ПО
Сотрудники.Пол
Такой подход является эталонным для архитектуры 1С, так как он не зависит от строковых данных и работает максимально быстро.