Как в запросе 1С выбрать один банковский счет контрагента с определенным дополнительным реквизитом при наличии нескольких?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В 1С:Предприятии часто возникает необходимость выбирать данные из нескольких однотипных объектов по определенным критериям, включая дополнительные реквизиты. Эта задача может быть особенно сложной для начинающих разработчиков, так как требует понимания механизма работы запросов, связей таблиц и специфики хранения дополнительных реквизитов. В этом руководстве мы подробно рассмотрим, как построить такой запрос, на примере выбора банковского счета контрагента в конфигурации 1С:Управление торговлей (УТ). Мы проанализируем различные подходы к решению этой задачи, от работы с дополнительными реквизитами до методов выбора единственной записи при наличии нескольких подходящих.

Понимание и детализация задачи

Прежде всего, давайте разберем поставленную задачу. Нам необходимо собрать информацию о банковских счетах контрагента, учитывая следующие условия:

  1. Источник данных: Элементы справочника БанковскиеСчетаКонтрагентов, связанные с полем Покупатель.
  2. Условие отбора по основным реквизитам: Счета должны быть действующими, то есть их реквизит Закрыт должен быть равен Ложь.
  3. Поля для вывода: Мы должны получить НомерСчета, а также информацию о банковском идентификационном коде (БИК): БИК.Наименование, БИК.КоррСчет, БИК.
  4. Приоритетный выбор при наличии нескольких счетов: Если для одного контрагента найдено более одного подходящего счета, необходимо выбрать тот, у которого дополнительный реквизит "ИмяДопРеквизита_наборБуквИСимволов" имеет значение Истина.

Важно отметить, что механизм работы с дополнительными реквизитами требует особого подхода, так как они хранятся отдельно от основных реквизитов объекта.

Работа с дополнительными реквизитами в запросах 1С

Дополнительные реквизиты — это мощный инструмент, позволяющий расширять функциональность объектов 1С без изменения структуры конфигурации. В конфигурации 1С:УТ значения дополнительных реквизитов объектов, таких как БанковскиеСчетаКонтрагентов, обычно хранятся в специальных регистрах сведений или табличных частях. Чаще всего для справочников и документов используются регистры сведений ЗначенияСвойствОбъектов или аналогичные структуры, а сами описания свойств (виды дополнительных реквизитов) хранятся в справочниках типа ВидыДополнительныхРеквизитов или ДополнительныеРеквизитыИСведения.

Чтобы получить значение дополнительного реквизита в запросе, мы должны выполнить следующие шаги:

  1. Соединение с объектом: Начнем с основной таблицы, например, Справочник.БанковскиеСчетаКонтрагентов.
  2. Соединение с таблицей значений свойств: Затем мы присоединяем к ней таблицу, хранящую значения свойств. В УТ это часто может быть виртуальная таблица ЗначенияСвойствОбъектов.СрезПоследних или прямой доступ к регистру сведений ЗначенияСвойствОбъектов. Для оптимальной работы с дополнительными реквизитами в запросах мы часто используем виртуальные таблицы из объекта метаданных РегистрСведений.ЗначенияСвойствОбъектов.
  3. Отбор по имени свойства: Для отбора по конкретному дополнительному реквизиту нам нужно соединиться со справочником, который описывает само свойство. В нашем случае это может быть справочник ВидыДополнительныхРеквизитов или ДополнительныеРеквизитыИСведения, где хранится Наименование нашего реквизита "ИмяДопРеквизита_наборБуквИСимволов".

Рассмотрим пример того, как мы можем соединиться с таблицами дополнительных реквизитов и выполнить отбор по имени свойства и его значению. Предположим, что наш дополнительный реквизит называется "ИмяДопРеквизита_наборБуквИСимволов" и он имеет тип "Булево".


ВЫБРАТЬ
    БанковскиеСчетаКонтрагентов.Ссылка,
    ЗначенияСвойств.Значение
ИЗ
    Справочник.БанковскиеСчетаКонтрагентов КАК БанковскиеСчетаКонтрагентов
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
        ПО БанковскиеСчетаКонтрагентов.Ссылка = ЗначенияСвойств.Объект
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыДополнительныхРеквизитов КАК ВидыДопРеквизитов
        ПО ЗначенияСвойств.Свойство = ВидыДопРеквизитов.Ссылка
ГДЕ
    ВидыДопРеквизитов.Наименование = "ИмяДопРеквизита_наборБуквИСимволов"
    И ЗначенияСвойств.Значение = ИСТИНА

В этом примере мы выполняем левое соединение, чтобы учесть счета, у которых данного дополнительного реквизита может не быть вовсе. Если реквизит имеет тип Булево, мы можем напрямую сравнить его Значение с ИСТИНА.

Выбор приоритетного счета из нескольких

Это ключевой момент задачи. Если для одного контрагента существует несколько банковских счетов, которые удовлетворяют условию Закрыт = Ложь, и, возможно, даже несколько из них имеют дополнительный реквизит "ИмяДопРеквизита_наборБуквИСимволов" равный Истина, нам необходимо выбрать только один. Рассмотрим два основных подхода.

Метод 1: Использование УПОРЯДОЧИТЬ ПО и ВЫБРАТЬ ПЕРВЫЕ 1

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

  1. Присвоение приоритета через сортировку: Мы можем создать поле-признак, которое будет отражать наличие нашего дополнительного реквизита со значением Истина. Затем мы будем сортировать по этому признаку в убывающем порядке. Счет, у которого дополнительный реквизит Истина, получит более высокий приоритет.
  2. Выбор первой записи: После сортировки мы используем конструкцию ВЫБРАТЬ ПЕРВЫЕ 1, чтобы получить только самую приоритетную запись.

Однако, как было отмечено в обсуждении, что делать, если несколько счетов имеют дополнительный реквизит Истина? В этом случае нам потребуется дополнительный критерий сортировки, который поможет однозначно определить один счет. Это может быть:

Давайте посмотрим, как это выглядит в запросе. Мы добавим в выборку условное поле, которое будет равно 1, если дополнительный реквизит равен Истина, и 0 в противном случае.


ВЫБРАТЬ
    БанковскиеСчетаКонтрагентов.Ссылка КАК Счет,
    БанковскиеСчетаКонтрагентов.НомерСчета,
    БанковскиеСчетаКонтрагентов.БИК.Наименование КАК НаименованиеБИК,
    БанковскиеСчетаКонтрагентов.БИК.КоррСчет КАК КоррСчетБИК,
    БанковскиеСчетаКонтрагентов.БИК КАК БИК,
    ВЫБОР
        КОГДА ЗначенияСвойств.Значение = ИСТИНА ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ КАК ПриоритетДопРеквизита
ИЗ
    Справочник.БанковскиеСчетаКонтрагентов КАК БанковскиеСчетаКонтрагентов
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
        ПО БанковскиеСчетаКонтрагентов.Ссылка = ЗначенияСвойств.Объект
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыДополнительныхРеквизитов КАК ВидыДопРеквизитов
        ПО ЗначенияСвойств.Свойство = ВидыДопРеквизитов.Ссылка
ГДЕ
    БанковскиеСчетаКонтрагентов.Закрыт = ЛОЖЬ
    И ВидыДопРеквизитов.Наименование = "ИмяДопРеквизита_наборБуквИСимволов"
УПОРЯДОЧИТЬ ПО
    ПриоритетДопРеквизита УБЫВ,
    БанковскиеСчетаКонтрагентов.НомерСчета ВОЗР

Этот запрос уже сортирует данные, но пока не выбирает только один счет. Чтобы выбрать один счет из всех подходящих по критерию приоритета, мы можем добавить ВЫБРАТЬ ПЕРВЫЕ 1 к верхней части запроса.


ВЫБРАТЬ ПЕРВЫЕ 1
    БанковскиеСчетаКонтрагентов.НомерСчета,
    БанковскиеСчетаКонтрагентов.БИК.Наименование КАК НаименованиеБИК,
    БанковскиеСчетаКонтрагентов.БИК.КоррСчет КАК КоррСчетБИК,
    БанковскиеСчетаКонтрагентов.БИК КАК БИК
ИЗ
    Справочник.БанковскиеСчетаКонтрагентов КАК БанковскиеСчетаКонтрагентов
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
        ПО БанковскиеСчетаКонтрагентов.Ссылка = ЗначенияСвойств.Объект
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыДополнительныхРеквизитов КАК ВидыДопРеквизитов
        ПО ЗначенияСвойств.Свойство = ВидыДопРеквизитов.Ссылка
ГДЕ
    БанковскиеСчетаКонтрагентов.Закрыт = ЛОЖЬ
    И ВидыДопРеквизитов.Наименование = "ИмяДопРеквизита_наборБуквИСимволов"
УПОРЯДОЧИТЬ ПО
    ВЫБОР
        КОГДА ЗначенияСвойств.Значение = ИСТИНА ТОГДА 1
        ИНАЧЕ 0
    КОНЕЦ УБЫВ,
    БанковскиеСчетаКонтрагентов.НомерСчета ВОЗР

Этот запрос выберет один наиболее приоритетный счет из всех существующих в системе, которые соответствуют условию Закрыт = ЛОЖЬ и у которых есть дополнительный реквизит "ИмяДопРеквизита_наборБуквИСимволов".

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


ВЫБРАТЬ
    КонтрагентыСчета.НомерСчета,
    КонтрагентыСчета.НаименованиеБИК,
    КонтрагентыСчета.КоррСчетБИК,
    КонтрагентыСчета.БИК
ИЗ
    (ВЫБРАТЬ
        БанковскиеСчетаКонтрагентов.Владелец КАК Контрагент,
        БанковскиеСчетаКонтрагентов.НомерСчета,
        БанковскиеСчетаКонтрагентов.БИК.Наименование КАК НаименованиеБИК,
        БанковскиеСчетаКонтрагентов.БИК.КоррСчет КАК КоррСчетБИК,
        БанковскиеСчетаКонтрагентов.БИК КАК БИК,
        ВЫБОР
            КОГДА ЗначенияСвойств.Значение = ИСТИНА ТОГДА 1
            ИНАЧЕ 0
        КОНЕЦ КАК ПриоритетДопРеквизита,
        МАКСИМУМ(ВЫБОР КОГДА ЗначенияСвойств.Значение = ИСТИНА ТОГДА 1 ИНАЧЕ 0 КОНЕЦ) ПО БанковскиеСчетаКонтрагентов.Владелец КАК МаксимальныйПриоритетПоКонтрагенту
    ИЗ
        Справочник.БанковскиеСчетаКонтрагентов КАК БанковскиеСчетаКонтрагентов
            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
            ПО БанковскиеСчетаКонтрагентов.Ссылка = ЗначенияСвойств.Объект
            ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыДополнительныхРеквизитов КАК ВидыДопРеквизитов
            ПО ЗначенияСвойств.Свойство = ВидыДопРеквизитов.Ссылка
    ГДЕ
        БанковскиеСчетаКонтрагентов.Закрыт = ЛОЖЬ
        И ВидыДопРеквизитов.Наименование = "ИмяДопРеквизита_наборБуквИСимволов"
    ) КАК КонтрагентыСчета
ГДЕ
    КонтрагентыСчета.ПриоритетДопРеквизита = КонтрагентыСчета.МаксимальныйПриоритетПоКонтрагенту
УПОРЯДОЧИТЬ ПО
    КонтрагентыСчета.Контрагент,
    КонтрагентыСчета.ПриоритетДопРеквизита УБЫВ,
    КонтрагентыСчета.НомерСчета ВОЗР

Этот пример более сложный. Он использует подзапрос, чтобы сначала определить максимальный приоритет для каждого контрагента, а затем во внешнем запросе выбирает только те счета, которые соответствуют этому максимальному приоритету. Дополнительная сортировка по НомерСчета помогает выбрать один, если приоритеты совпадают.

Метод 2: Использование оператора ВЫБОР КОГДА ТОГДА для определения приоритета

Оператор ВЫБОР КОГДА ТОГДА очень гибок и может быть использован для создания сложной логики выбора прямо внутри запроса. Он позволяет оценить различные условия и вернуть соответствующее значение. В нашем случае мы можем использовать его для создания поля, которое будет явно указывать на приоритетный счет. Это аналогично созданию поля ПриоритетДопРеквизита в предыдущем методе, но мы можем использовать его для более сложных условий, если их будет несколько.

Например, мы можем выбрать счета, у которых доп. реквизит Истина, а затем, если таких нет, выбрать просто любой первый попавшийся счет. Это потребует использования объединения:


ВЫБРАТЬ
    БанковскиеСчетаКонтрагентов.Владелец КАК Контрагент,
    БанковскиеСчетаКонтрагентов.НомерСчета,
    БанковскиеСчетаКонтрагентов.БИК.Наименование КАК НаименованиеБИК,
    БанковскиеСчетаКонтрагентов.БИК.КоррСчет КАК КоррСчетБИК,
    БанковскиеСчетаКонтрагентов.БИК КАК БИК
ИЗ
    Справочник.БанковскиеСчетаКонтрагентов КАК БанковскиеСчетаКонтрагентов
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
        ПО БанковскиеСчетаКонтрагентов.Ссылка = ЗначенияСвойств.Объект
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыДополнительныхРеквизитов КАК ВидыДопРеквизитов
        ПО ЗначенияСвойств.Свойство = ВидыДопРеквизитов.Ссылка
ГДЕ
    БанковскиеСчетаКонтрагентов.Закрыт = ЛОЖЬ
    И ВидыДопРеквизитов.Наименование = "ИмяДопРеквизита_наборБуквИСимволов"
    И ЗначенияСвойств.Значение = ИСТИНА

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

ВЫБРАТЬ
    БанковскиеСчетаКонтрагентов.Владелец,
    БанковскиеСчетаКонтрагентов.НомерСчета,
    БанковскиеСчетаКонтрагентов.БИК.Наименование,
    БанковскиеСчетаКонтрагентов.БИК.КоррСчет,
    БанковскиеСчетаКонтрагентов.БИК
ИЗ
    Справочник.БанковскиеСчетаКонтрагентов КАК БанковскиеСчетаКонтрагентов
ГДЕ
    БанковскиеСчетаКонтрагентов.Закрыт = ЛОЖЬ
    И НЕ БанковскиеСчетаКонтрагентов.Ссылка В
        (ВЫБРАТЬ
            ЗначенияСвойств.Объект
        ИЗ
            РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойств
                ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыДополнительныхРеквизитов КАК ВидыДопРеквизитов
                ПО ЗначенияСвойств.Свойство = ВидыДопРеквизитов.Ссылка
        ГДЕ
            ВидыДопРеквизитов.Наименование = "ИмяДопРеквизита_наборБуквИСимволов"
            И ЗначенияСвойств.Значение = ИСТИНА)

Данный подход выбирает сначала все счета с приоритетным доп. реквизитом, а затем (если у контрагента нет таких счетов) выбирает любые другие счета. Затем над этим результатом можно выполнить группировку по контрагенту с выбором ПЕРВЫЕ 1 для каждого, чтобы получить окончательный результат. Однако, это может быть более сложным для начинающего.

Советы по работе с конструктором запросов 1С

Конструктор запросов является полезным инструментом, особенно для начинающих, поскольку он позволяет визуально строить запросы, выбирать таблицы, создавать связи и условия. Однако, для сложных запросов, особенно тех, которые включают нетривиальные соединения с дополнительными реквизитами или подзапросы, конструктор может быть ограничен.

В случае с дополнительными реквизитами, их связь с основной таблицей может быть не всегда очевидна в конструкторе, поскольку они хранятся в отдельных объектах. Поэтому ручное добавление связей через ЛЕВОЕ СОЕДИНЕНИЕ с регистрами сведений (например, РегистрСведений.ЗначенияСвойствОбъектов) и справочниками (например, Справочник.ВидыДополнительныхРеквизитов) является предпочтительным методом.

Заключение

Составление запросов в 1С, особенно с учетом таких специфических механизмов, как дополнительные реквизиты и выбор приоритетной записи из нескольких, требует внимательности и понимания структуры данных. Мы рассмотрели основные подходы к решению задачи, используя конструкции УПОРЯДОЧИТЬ ПО, ВЫБРАТЬ ПЕРВЫЕ 1 и оператор ВЫБОР КОГДА ТОГДА. Помните, что для достижения наилучшего результата может потребоваться комбинация этих методов и тщательное тестирование запроса на ваших реальных данных. Практика написания запросов вручную с последующим использованием конструктора для форматирования значительно улучшит ваши навыки в 1С.

← На главную