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