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