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