В практике разработки на платформе 1С:Предприятие часто возникает специфическая задача из области теории баз данных, известная как реляционное деление. Суть ее заключается в следующем: необходимо найти такие значения, которые присутствуют в связке с абсолютно каждым параметром из заданного набора. Например, если у нас есть список товаров и их свойств, мы хотим найти свойство, которое характерно для всех выбранных товаров одновременно.
В этой статье мы подробно разберем, как реализовать подобную логику в языке запросов 1С, проанализируем ошибки новичков и рассмотрим наиболее надежный способ, учитывающий возможные дубликаты в данных.
Представим таблицу (например, Регистр Сведений), где хранятся пары Параметр и Значение. Если в таблице присутствуют записи:
Мы видим, что Значение2 встречается у всех трех параметров. Именно его нам и нужно извлечь. Основная сложность заключается в том, что мы не знаем заранее количество уникальных параметров, и нам нужно вычислить его динамически в рамках того же запроса.
Рассмотрим первый логический подход. Нам нужно выполнить три шага:
Проанализируем пример кода, реализующий эту логику:
// Шаг 1: Получаем общее количество уникальных параметров
ВЫБРАТЬ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_ПараметрыЗначения.Параметр) КАК ВсегоПараметров
ПОМЕСТИТЬ ВТ_КоличествоПараметров
ИЗ
ВТ_ПараметрыЗначения КАК ВТ_ПараметрыЗначения;
////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Группируем по значениям и сравниваем количество вхождений
ВЫБРАТЬ
ВТ_ПараметрыЗначения.Значение КАК Значение
ИЗ
ВТ_ПараметрыЗначения КАК ВТ_ПараметрыЗначения
СГРУППИРОВАТЬ ПО
ВТ_ПараметрыЗначения.Значение
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_ПараметрыЗначения.Параметр) = (ВЫБРАТЬ ВсегоПараметров ИЗ ВТ_КоличествоПараметров)
Этот метод хорош своей краткостью, но использование КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...) может замедлять работу на больших объемах данных. Кроме того, важно использовать именно РАЗЛИЧНЫЕ, чтобы избежать ложных срабатываний, если одна и та же пара Параметр-Значение случайно запишется в таблицу дважды.
Рассмотрим более сложную, но крайне надежную ситуацию, когда нам нужно получить результат в виде полной таблицы (Параметр | Значение) для всех общих значений. Этот метод полезен, когда в исходных данных много дублей или сложная структура. Разберем его по шагам.
Шаг 1. Очистка данных. Сначала мы избавимся от дубликатов, выбрав только уникальные пары Параметр и Значение во временную таблицу.
ВЫБРАТЬ РАЗЛИЧНЫЕ
ВТ_ПараметрыЗначения.Параметр КАК Параметр,
ВТ_ПараметрыЗначения.Значение КАК Значение
ПОМЕСТИТЬ ВТ_ПараметрыЗначенияРазличные
ИЗ
ВТ_ПараметрыЗначения КАК ВТ_ПараметрыЗначения;
Шаг 2. Подсчет фактических вхождений. Теперь мы считаем, сколько раз каждое значение встречается в нашей "чистой" таблице.
ВЫБРАТЬ
ВТ_ПараметрыЗначенияРазличные.Значение КАК Значение,
КОЛИЧЕСТВО(*) КАК Количество
ПОМЕСТИТЬ ВТ_ФактическиеГруппировки
ИЗ
ВТ_ПараметрыЗначенияРазличные КАК ВТ_ПараметрыЗначенияРазличные
СГРУППИРОВАТЬ ПО
ВТ_ПараметрыЗначенияРазличные.Значение;
Шаг 3. Создание эталона. Теперь мы выясним, сколько уникальных параметров существует всего. В идеальном случае (если значение общее для всех), количество вхождений значения должно равняться количеству уникальных параметров.
ВЫБРАТЬ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВТ_ПараметрыЗначения.Параметр) КАК КоличествоЭталон
ПОМЕСТИТЬ ВТ_ЭталонноеКоличество
ИЗ
ВТ_ПараметрыЗначения КАК ВТ_ПараметрыЗначения;
Шаг 4. Финальное соединение. Мы соединяем результаты подсчета с эталонным числом. Если количество совпало — значение является общим.
ВЫБРАТЬ
ВТ_ФактическиеГруппировки.Значение
ИЗ
ВТ_ФактическиеГруппировки КАК ВТ_ФактическиеГруппировки
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ЭталонноеКоличество КАК ВТ_ЭталонноеКоличество
ПО ВТ_ФактическиеГруппировки.Количество = ВТ_ЭталонноеКоличество.КоличествоЭталон;
Проанализируем несколько технических моментов, которые помогут сделать ваш запрос быстрее:
ИНДЕКСИРОВАТЬ ПО для полей Параметр и Значение во временных таблицах. Это значительно ускорит операции СГРУППИРОВАТЬ и СОЕДИНЕНИЕ.Значение имеет составной тип, группировка по нему будет работать медленнее. По возможности старайтесь приводить значения к конкретному типу или сравнивать ссылки.Мы рассмотрели, как реализовать поиск пересечений множеств в запросах 1С. Основной принцип — сравнение количества уникальных владельцев (параметров) у конкретного значения с общим количеством уникальных владельцев в выборке. Помните, что использование РАЗЛИЧНЫЕ внутри функции КОЛИЧЕСТВО — это самый простой путь, но предварительная подготовка уникальных пар во временной таблице часто оказывается более производительной на "тяжелых" регистрах.