Имя: Пароль:
1C
1С v8
Пакетный запрос номенклатуры по свойствам
, ,
0 Lengros
 
15.01.17
19:57
Доброго времени суток. Уважаемые знатоки, подскажите как оно будет грамотнее организовать.

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

Вот что сделал я.

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


На выходе запрос выдаёт ссылки номенклатуры, которые соответствуют хотя бы одному из задаваемых параметров "Свойство-Значение", что не есть правильно. Плюс повторяющиеся значения, если Номенклатура попадает сразу по двум параметрам.
Как правильно вписать сюда условия отбор исходя из поставленной задачи?.
1 mkalimulin
 
15.01.17
21:02
(0) Убрать повторы просто - группируешь по номенклатуре.

Как убрать неполные группы:

ВЫБРАТЬ
ИсходнаяВыборка.Ссылка
ИЗ ИсходнаяВыборка КАК ИсходнаяВыборка
ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ
ПО ИсходнаяВыборка.Свойство = ВТ.Свойство
СГРУППИРОВАТЬ ПО ИсходнаяВыборка.Ссылка
ИМЕЮЩИЕ
МИНИМУМ(ВЫБОР КОГДА ВТ.Свойство ЕСТЬ NULL ТОГДА
0
ИНАЧЕ
1
КОНЕЦ)=1

Синтаксис не проверял.
2 Lengros
 
16.01.17
09:54
Так тоже не решается основная проблема отбора по двум заданным параметрам Свойство-Значение одновременно.
В результате выдаёт совпадение хотя бы по одному из них.
3 mkalimulin
 
16.01.17
10:06
(2) Так решается. Смотри внимательно. Условие ИМЕЮЩИЕ отбирает только те группы, у которых не NULLов, т.е все свойства имеются в наличии.
4 mkalimulin
 
16.01.17
10:12
+(3) Извини. Действительно в ПО пропустил второе условие:

ПО ИсходнаяВыборка.Свойство = ВТ.Свойство
И ИсходнаяВыборка.ЗначениеСвойства = ВТ.ЗначениеСвойства
5 Lengros
 
16.01.17
12:05
(5) А ведь работает. Что-то у меня глаза совсем замылились, раз уже не вижу такое довольно простое решение. Спасибо большое за подсказку :)
Теперь осталось решить только один нюанс. Этот запрос

ВЫБРАТЬ
ИсходнаяВыборка.Ссылка
ИЗ ИсходнаяВыборка КАК ИсходнаяВыборка
ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ
ПО ИсходнаяВыборка.Свойство = ВТ.Свойство
И ИсходнаяВыборка.ЗначениеСвойства = ВТ.ЗначениеСвойства
СГРУППИРОВАТЬ ПО ИсходнаяВыборка.Ссылка
ИМЕЮЩИЕ
МИНИМУМ(ВЫБОР КОГДА ВТ.Свойство ЕСТЬ NULL ТОГДА
0 ИНАЧЕ 1 КОНЕЦ)=1

выдаёт группы у которых все свойства в наличии, включяя и те, у которых изначально свойств меньше, чем заданно параметрами.
6 Ildarovich
 
16.01.17
12:19
Вот тут: http://catalog.mista.ru/public/164951/ была похожая задача. Статья интересна тем, что сравнивалось и подробно разбиралось много разных запросов.
7 Ildarovich
 
16.01.17
12:51
+(6) перечитал заново статью по ссылке. Условия конкурса в ней были специально выбраны так, чтобы исключить простые решения.

Простым решением в рассматриваемом здесь случае будет решение из (5), где условие изменено на
ИМЕЮЩИЕ СУММА(ВЫБОР КОГДА ВТ.Свойство ЕСТЬ NULL ТОГДА
0 ИНАЧЕ 1 КОНЕЦ)=&ЧислоЗаданныхСвойств
8 Lengros
 
17.01.17
00:19
(8) Большое спасибо. Действительно то, что надо.
Всё сделал, всё получилось.
Благодарю всех за поддержку, тема закрыта.
Если кому понадобится результат, то он тут:

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

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

9 Lengros
 
17.01.17
00:22
(6) Большое спасибо и действительно то, что надо сюда, чуть промазал :)

(8) Запрос писал и тестировал на базе 1с 8.2 УТ для Беларуси 2.0.43
10 i_rodionov
 
17.01.17
00:29
(9) Можешь сократить время выборки. ЗначенияСвойствОбъектов.Объект - скорее всего составной тип. база будет делать лишние соединения. Применяй ВЫРАЗИТЬ
11 i_rodionov
 
17.01.17
00:34
(9)
ПО
   СпрНоменклатура.Ссылка = ЗначенияСвойствОбъектов.Объект
ГДЕ
  СпрНоменклатура.ЭтоГруппа = ЛОЖЬ

Можно сократить до  
ПО
   (СпрНоменклатура.Ссылка = ЗначенияСвойствОбъектов.Объект)
   И (Не СпрНоменклатура.ЭтоГруппа)
Закон Брукера: Даже маленькая практика стоит большой теории.