Как в запросе 1С найти записи из одной таблицы, которых нет в другой?

Программист
← На главную

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

Проанализируем конкретный пример. Есть две таблицы (Т1 и Т2) с одинаковой структурой: поля Номенклатура и Количество.

Таблица Т1:

  1. Номенклатура: Н1, Количество: 10
  2. Номенклатура: Н2, Количество: 20
  3. Номенклатура: Н3, Количество: 30

Таблица Т2:

  1. Номенклатура: Н1, Количество: 10
  2. Номенклатура: Н2, Количество: 20

Наша цель — написать запрос, который вернет только те строки из Т1, которых нет в Т2. В данном случае результат должен быть:

  1. Номенклатура: Н3, Количество: 30

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

Решение 1: Использование ЛЕВОГО СОЕДИНЕНИЯ (LEFT JOIN)

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

Разберем по шагам:

  1. Берем первую таблицу (Т1) как основу запроса.
  2. Используем конструкцию ЛЕВОЕ СОЕДИНЕНИЕ, чтобы присоединить к ней вторую таблицу (Т2).
  3. Ключевой момент: в условии соединения ПО мы должны перечислить все поля, по которым ищем совпадение. В нашем случае это Т1.Номенклатура = Т2.Номенклатура И Т1.Количество = Т2.Количество.
  4. Если для строки из Т1 находится полное соответствие в Т2, то поля из Т2 будут заполнены значениями. Если же соответствия не найдено, то все поля, выбираемые из Т2, будут иметь значение NULL.
  5. На последнем шаге мы добавляем условие ГДЕ, чтобы отфильтровать результат и оставить только те строки, где поле из второй таблицы равно NULL. Это и будут наши уникальные записи из Т1.

Посмотрим на пример кода:


ВЫБРАТЬ
    Т1.Номенклатура,
    Т1.Количество
ИЗ
    Т1 КАК Т1
        ЛЕВОЕ СОЕДИНЕНИЕ Т2 КАК Т2
        ПО Т1.Номенклатура = Т2.Номенклатура
            И Т1.Количество = Т2.Количество
ГДЕ
    Т2.Номенклатура ЕСТЬ NULL

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

Решение 2: Математический метод с ОБЪЕДИНИТЬ ВСЕ и группировкой

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

Логика метода следующая:

  1. Создаем общий набор данных из двух таблиц с помощью оператора ОБЪЕДИНИТЬ ВСЕ. Важно использовать именно ОБЪЕДИНИТЬ ВСЕ, так как он не удаляет дубликаты и работает быстрее, чем просто ОБЪЕДИНИТЬ.
  2. При выборке данных из второй таблицы (Т2) мы инвертируем знак у числового поля, то есть умножаем Количество на -1.
  3. Полученный объединенный результат мы группируем по ключевому полю (Номенклатура) и для каждой группы вычисляем сумму по полю Количество с помощью агрегатной функции СУММА().
  4. Если в Т1 и Т2 были абсолютно одинаковые записи (например, Н1, 10), то их сумма станет равна нулю (10 + (-10) = 0).
  5. В конце с помощью условия ИМЕЮЩИЕ мы отбираем только те группы, где итоговая сумма не равна нулю.

Пример запроса:


ВЫБРАТЬ
    ВложенныйЗапрос.Номенклатура,
    СУММА(ВложенныйЗапрос.Количество) КАК Количество
ИЗ
    (ВЫБРАТЬ
        Т1.Номенклатура КАК Номенклатура,
        Т1.Количество КАК Количество
    ИЗ
        Т1 КАК Т1

    ОБЪЕДИНИТЬ ВСЕ

    ВЫБРАТЬ
        Т2.Номенклатура,
        -Т2.Количество
    ИЗ
        Т2 КАК Т2) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
    ВложенныйЗапрос.Номенклатура

ИМЕЮЩИЕ
    СУММА(ВложенныйЗапрос.Количество) > 0

Важное замечание: условие в секции ИМЕЮЩИЕ зависит от задачи. Если нужно найти только те позиции, которые есть в Т1 и отсутствуют в Т2, то условие будет СУММА(Количество) > 0. Если же нужно найти любые расхождения (в том числе позиции, которые есть в Т2, но нет в Т1), то условие будет СУММА(Количество) <> 0.

Решение 3: Использование вложенного запроса с "НЕ В" (NOT IN)

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

Пример запроса для сравнения по одному полю:


ВЫБРАТЬ
    Т1.Номенклатура,
    Т1.Количество
ИЗ
    Т1 КАК Т1
ГДЕ
    Т1.Номенклатура НЕ В (ВЫБРАТЬ Т2.Номенклатура ИЗ Т2)

Однако у этого метода есть существенный недостаток для нашей задачи: он позволяет легко сравнивать таблицы только по одному полю. В нашем примере он не учитывает поле Количество. Чтобы учесть несколько полей, конструкцию пришлось бы усложнять, например, с помощью кортежей (что поддерживается в 1С), но это часто делает запрос менее читаемым и производительным по сравнению с ЛЕВЫМ СОЕДИНЕНИЕМ. Подобные сложности часто возникают, когда проводится поиск и замена битых ссылок справочников и требуется строгая фильтрация объектов.


// Пример для нескольких полей (используйте с осторожностью)
ГДЕ
    (Т1.Номенклатура, Т1.Количество) НЕ В 
        (ВЫБРАТЬ
            Т2.Номенклатура,
            Т2.Количество
        ИЗ
            Т2)

Для сравнения по нескольким полям метод с ЛЕВЫМ СОЕДИНЕНИЕМ остается более надежным и универсальным решением.

← На главную