Имя: Пароль:
1C
1С v8
Как правильно составить условие запроса?
,
0 МешочекЗнаний
 
13.08.21
14:04
Приветствую уважаемые.
Безбожно туплю на запросе. Упрощённый пример: У характеристики номенклатуры имеются дополнительные реквизиты (Длина, Ширина, Высота, Цвет).

--------------------------------
- Длина - Ширина - Высота - Цвет
- 1     - 2      - 3      - Серый
- 1     - 2      - 4      - Серый      
- 2     - 2      - 3      - Серый
--------------------------------

Мне например нужно выбрать характеристику с длиной = 1; шириной = 2; высотой = 4; Цвет - Серый.
Не могу понять как правильно составить запрос чтобы правильно получить данные.

Попробовал так:
[spoiler]
        |ГДЕ
        |    (ХарактеристикиНоменклатурыДополнительныеРеквизиты.Свойство = &ДлинаСвойство
        |                И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Значение = &ДлинаЗначение
        |            И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Свойство = &ШиринаСвойство
        |                И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Значение = &ШиринаЗначение
        |            И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Свойство = &ТолщинаСвойство
        |                И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Значение = &ТолщинаЗначение)
[/spoiler]

Но запрос ничего не возвращает, это логично т.к. на одно и то же поле (свойство) накладывается взаимоисключающие непересекающиеся условие


Попробовал так:
[spoiler]
        |ГДЕ
        |    (ХарактеристикиНоменклатурыДополнительныеРеквизиты.Свойство, ХарактеристикиНоменклатурыДополнительныеРеквизиты.Значение) В (&ТЗ_СвойстваИЗначения)
[/spoiler]

Запрос возвращает все данные, где встречается хоть одна комбинация из доп реквизитов.

В принципе могу решить проблему и наговнокодить типо такого (Пошагово отсекать лишние данные), но по-моему это плохой вариант.
[spoiler]
        "ВЫБРАТЬ
        |    ХарактеристикиНоменклатурыДополнительныеРеквизиты.Ссылка КАК Ссылка
        |ПОМЕСТИТЬ ВТ_ОтборПоДлине
        |ИЗ
        |    Справочник.ХарактеристикиНоменклатуры.ДополнительныеРеквизиты КАК ХарактеристикиНоменклатурыДополнительныеРеквизиты
        |ГДЕ
        |    ХарактеристикиНоменклатурыДополнительныеРеквизиты.Свойство = &ДлинаСвойство
        |    И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Значение = &ДлинаЗначение
        |;
        |
        |////////////////////////////////////////////////////////////////////////////////
        |ВЫБРАТЬ
        |    ХарактеристикиНоменклатурыДополнительныеРеквизиты.Ссылка КАК Ссылка
        |ПОМЕСТИТЬ ВТ_ОтборПоШирине
        |ИЗ
        |    Справочник.ХарактеристикиНоменклатуры.ДополнительныеРеквизиты КАК ХарактеристикиНоменклатурыДополнительныеРеквизиты
        |ГДЕ
        |    ХарактеристикиНоменклатурыДополнительныеРеквизиты.Свойство = &ШиринаСвойство
        |    И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Значение = &ШиринаЗначение
        |    И ХарактеристикиНоменклатурыДополнительныеРеквизиты.Ссылка В
        |            (ВЫБРАТЬ
        |                ВТ_ОтборПоДлине.Ссылка
        |            ИЗ
        |                ВТ_ОтборПоДлине)...
[/spoiler]

Прошу помочь мыслями, как сделать по правильному.
1 Волшебник
 
модератор
13.08.21
14:08
на каждое свойство нужно отдельное левое соединение и отдельное поле
2 Said_We
 
13.08.21
14:37
(0) Не нужны левые соединения....
Запрос по характеристикам
3 Said_We
 
13.08.21
14:59
(0) В твоем случае необходимо найти все номенклатуры, у которых заданные свойства одновременно.
1) Свойство1 = Значение1 ИЛИ Свойство2 = Значение2 ИЛИ Свойство3 = Значение3 ИЛИ Свойство4 = Значение4
2) Полученную таблицу разворачиваешь и сворачиваешь как в ссылке (2) через Макс(Выбрать Когда...конец)
3) Накладываешь условие одновременное
   Свойство1 = Значение1 И Свойство2 = Значение2 И Свойство3 = Значение3 И Свойство4 = Значение4

Нет тут никаких левых соединений и т.д.
4 Said_We
 
13.08.21
15:06
(0) Суть я понятно расписал?
5 Kassern
 
13.08.21
15:09
(3) Чет зачастили эти темы с характеристиками в последнее время)
6 Said_We
 
13.08.21
15:12
(5) Есть такое. Сам удивляюсь.
Я не знаю почему эти характеристики постоянно хотят получать левыми соединениями и постоянно отдельно по каждому свойству отдельно.
В типовых примерно так же упорно делают через левое соединение - это страшно медленно работает.
Зачем - не знаю.
7 Kassern
 
13.08.21
15:30
(6) чтобы не потерять данные из основной таблицы видимо.
8 Said_We
 
13.08.21
15:33
(7) Если необходимо получить набор свойств для списка номенклатуры, то это дополнительное объединение с пустыми свойствами.
Это как раз задача из ссылки в (2). Опять же нет там соединения.
9 Said_We
 
13.08.21
15:35
(7) По ссылке в (2) пост 28. Нет потерь никаких. Пояснения есть :-)
10 RomanYS
 
13.08.21
15:55
(8) ни разу не понятно чем юнион с выбором и группировкой лучше вполне естественных для данной задачи соединений. Ну и в (0) задача несколько отличается от (2), здесь даже левые соединения не нужны - с внутренними должно быть быстрее
11 Said_We
 
13.08.21
16:05
(10) "ем юнион с выбором и группировкой лучше " - быстрее.
12 Said_We
 
13.08.21
18:29
(10) "вполне естественных для данной задачи соединений" - не соглашусь, там где можно обойтись без JOIN там они не естественны.
13 RomanYS
 
13.08.21
22:18
(11) замеры покажешь?
(12) всегда считал группировки бОльшим злом чем джойн
14 sapphire
 
14.08.21
00:58
(5) Понеже не умеют их готовить и сие самая захламленная таблица
15 sapphire
 
14.08.21
01:01
Еще хуже, если характеристики замножены, например, использованы доп свойства.
Нужно:
1) Типизировать владельца характеристики с отбором по наименованию
2) Отобрать выбранные в п 1 по заданному критерию
16 VS-1976
 
14.08.21
01:25
Примерно можно сделать так. Суть набросал, а там если что подправишь

ВЫБРАТЬ
    Свойство,
    Значение

ПОМЕСТИТЬ тзСвойстваОбъекта

ИЗ
    &ТаблицаСвойствОбъекта КАК тзСвойстваОбъекта
;

ВЫБРАТЬ
    тзДопРеквизиты.Ссылка КАК Характеристика
ИЗ
    тзСвойстваОбъекта,

    ( ВЫБРАТЬ КОЛИЧЕСТВО( Свойство ) КАК КолСвойств ИЗ тзСвойстваОбъекта) КАК тзКоличество

    СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры.ДополнительныеРеквизиты КАК тзДопРеквизиты
        ПО тзДопРеквизиты.Свойство = тзСвойстваОбъекта.Свойство
         И тзДопРеквизиты.Значение = тзСвойстваОбъекта.Значение

СГРУППИРОВАТЬ ПО
    тзДопРеквизиты.Ссылка

ИМЕЮЩИЕ
    КОЛИЧЕСТВО( тзДопРеквизиты.Ссылка ) = тзКоличество.КолСвойств
17 VS-1976
 
14.08.21
01:43
(16) Можно так же убрать соединение с количеством, передав количество параметром ( что бы поэкономить память )

ИМЕЮЩИЕ
    КОЛИЧЕСТВО( тзДопРеквизиты.Ссылка ) = &КолСвойств
18 МешочекЗнаний
 
14.08.21
11:16
(4) Благодарю за ответ! Посидел, сделал похожий запрос на своих данных, получил требуемый результат. Красивое решение без использования соединений. Добавил способ в свой багаж знаний.
(10) Попробовал с внутренним соединением, получается наглядно и понятно. Скорее всего на этом способе остановлюсь т.к. и скорость работы хорошая, и после меня кто будет сопровождать легче будет разобрать запрос.
(16) Спасибо за идею. Попробовал этот способ, но на моих данных запрос отрабатывает в 5 раз медленней чем в (4) или (10).
19 VS-1976
 
14.08.21
19:40
(18) Можно в принципе убрать соединение ( не универсально но всё же ), попробуй, может так быстрее )

ВЫБРАТЬ
    Ссылка КАК Характеристика
ИЗ
    Справочник.ХарактеристикиНоменклатуры.ДополнительныеРеквизиты
ГДЕ
    ( Свойство = &ДлинаСвойство И Значение = &ДлинаЗначение )
    Или ( Свойство = &ДлинаСвойство И Значение = &ШиринаЗначение )
    Или ( Свойство = &ТолщинаСвойство И Значение = &ТолщинаЗначение )
    Или ( Свойство = &ЦветСвойство И Значение = &ЦветЗначение )

СГРУППИРОВАТЬ ПО
    Ссылка

ИМЕЮЩИЕ
    КОЛИЧЕСТВО( Ссылка ) = 4
20 VS-1976
 
14.08.21
19:45
(19) Пречатка
    Или ( Свойство = &ШиринаСвойство
21 VS-1976
 
14.08.21
20:04
(19) Теоретически этот запрос можно написать так, что бы он работал ещё быстрее, при условии что "Значение" жутко составной тип и записей миллионы. Что бы не подымать много данных с диска, в начале можно определиться со свойствами. Свойства лежат отдельной индексной таблице и она не большая. Отобрать те характеристики, у которых все свойства есть ( заполнены ), а потом уже фильтровать по значениям но там уже будет соединение по индексу. Теоретически можно уменьшить I/O
22 Said_We
 
15.08.21
12:17
(13) В (18) замер производительности.
Если внимательно почитаешь ветку в (2), то там тоже есть замер производительности. На данных у автора получилось в 10 раз быстрее чем с джинами. Почему так - тоже расписано в ветке.
Ещё раз здесь перефразирую пост 29 в (2) "JOIN - это убийца производительности запросов.". Так было всегда и 10 лет назад и 20 лет назад и 30 лет назад. Сейчас с наличием оконных функций можно максимально обходится без JOIN, .... но не в 1С. 1С уже отстали на 10 лет от всего мира в части SQL. Уже в 2018 году оконные функции появились в SQLLite, который пишет один человек, а огромный штат 1С не смог и не хочет. Выигрыш в производительности зачастую доходит до нескольких порядков. Проверял запросы на чистом SQL с использованием оконных функций и аналогичные по функционалу с JOIN. Это просто небо и земля.
23 Said_We
 
15.08.21
12:26
(18) "Скорее всего на этом способе остановлюсь т.к. и скорость работы хорошая" - это пока у тебя задача найти все, у которых одновременно свойства такие-то.
А как только задача встанет, например:
* Найти и показать вместе со свойствами все номенклатурные позиции у которых: одно из свойств, такое-то ИЛИ другое свойство такое-то ИЛИ...
* Найти значение пяти свойств для перечня номенклатуры.

То использовать Внутреннее Соединение уже не сможешь и будет не быстро :-)

А решение в (2) универсальное и быстрое практически при любой постановки задачи про свойства.
24 RomanYS
 
15.08.21
12:26
(22) только в (18) вывод обратный твоему
25 Said_We
 
15.08.21
12:32
(24) В (23) пояснения.
26 Said_We
 
15.08.21
12:44
(20) + всё в подзапрос и свернуть по "ВЫБРАТЬ т.Характеристика КАК Характеристика" или через выбрать различные или группировкой. Дабы по 4-ре раза одного и того же не было.
27 Said_We
 
15.08.21
12:55
(13) "всегда считал группировки бОльшим злом чем джойн" - просто так ТАК считал или замерял производительность?
28 VS-1976
 
15.08.21
14:54
(26) Не понял, а как по твоему будет 4-ре раза одного и того же? ). Если запись одна для одной характеристики и свойству, почему их должно быть четыре? 4-ре записи будет тогда, когда все условия выполнены. Группировка и так есть СГРУППИРОВАТЬ ПО Ссылка - по этому ссылка вернётся в единственном числе, а условие ИМЕЮЩИЕ КОЛИЧЕСТВО( Ссылка ) = 4 отфильтрует те группы, у которых условия не выполены, то есть не все 4 свойства заполныны или заполнено хотя бы одно значение из четырёх не тем значением.
29 Said_We
 
15.08.21
15:06
(28) Да - не увидел.