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