|   |   | 
| 
 | Запросы в 1с | ☑ | ||
|---|---|---|---|---|
| 0
    
        abask 06.12.22✎ 15:29 | 
        есть справочник1
 есть документ1 в документе есть реквизит со ссылкой на справочник1 задача вывести все элементы справочник1 которые не используются в документ1 есть запрос: ВЫБРАТЬ Справочник1.Ссылка КАК Ссылка ИЗ Документ.Документ1 КАК Документ1 ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Справочник1 КАК Справочник1 ПО (Документ1.Реквизит1 <> Справочник1.Ссылка) вроде все работает. указываю в одном из документов элемент справочник1 и выводятся все элементы справочник1 кроме указанного но если не ни одного документа, то не выводится ничего, а должно выводиться все т.е. при отсутствии документов Соединение как-то неправильно отрабатывает одним запросом это можно сделать? | |||
| 1
    
        Ryzeman 06.12.22✎ 15:31 | 
        ВЫБРАТЬ
 Справочник1.Ссылка КАК Ссылка ИЗ Справочник.Справочник1 КАК Справочник1 ЛЕВОЕ СОЕДИНЕНИЕ Документ.Документ1 КАК Документ1 ПО (Документ1.Реквизит1 = Справочник1.Ссылка) ГДЕ Документ1.Ссылка ЕСТЬ NULL | |||
| 4
    
        Ryzeman 06.12.22✎ 15:34 | 
        Либо от противного, должно быстрее работать.
 ВЫБРАТЬ Справочник1.Ссылка КАК Ссылка ПОМЕСТИТЬ ВТ_ИСключаемые ИЗ Справочник.Справочник1 КАК Справочник1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Документ1 КАК Документ1 ПО (Документ1.Реквизит1 = Справочник1.Ссылка); //////////////////////// ВЫБРАТЬ Справочник1.Ссылка КАК Ссылка ИЗ Справочник.Справочник1 КАК Справочник1 ГДЕ Справочник1.Ссылка НЕ В (ВЫБРАТЬ ВТ_ИСключаемые.Ссылка КАК Ссылка ИЗ ВТ_ИСключаемые КАК ВТ_ИСключаемые) | |||
| 6
    
        lodger 06.12.22✎ 15:48 | 
        ВЫБРАТЬ
 Справочник1.Ссылка ИЗ Справочник.Справочник1 КАК Справочник1 ГДЕ НЕ Справочник1.Ссылка В (ВЫБРАТЬ РАЗЛИЧНЫЕ Документ1.Справочник1 ИЗ Документ.Документ1КАК Документ1 ГДЕ НЕ Документ1.ПометкаУдаления И ПоступлениеТоваров.Проведен) И НЕ Справочник1.ПометкаУдаления | |||
| 7
    
        Kassern 06.12.22✎ 15:50 | 
        (6) Зачем вы ТСу психику портите вложенными запросами?) Еще за правило возьмет так писать, потом сильно удивляться будет в быстродействии.     | |||
| 8
    
        lodger 06.12.22✎ 15:58 | 
        (7) а наркоманские связи в (0),(1) и (4) это будто нормально?     | |||
| 9
    
        Kassern 06.12.22✎ 16:03 | 
        (8) ага, нормально. По идее должно работать быстрее. В вашем случае так же создаются связи таблиц, только неявным способом и разные SQL могут по разному план запроса построить.     | |||
| 10
    
        Курцвейл 06.12.22✎ 16:24 | 
        (8) Признавайся, пил сегодня мухоморовый чай или нет?     | |||
| 11
    
        Курцвейл 06.12.22✎ 16:27 | 
        (4) Почти верно
 ВЫБРАТЬ Справочник1.Ссылка КАК Ссылка ПОМЕСТИТЬ ВТ_ИСключаемые ИЗ Справочник.Справочник1 КАК Справочник1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Документ1 КАК Документ1 ПО (Документ1.Реквизит1 = Справочник1.Ссылка) ИНДЕКСИРОВАТЬ ПО Ссылка; //////////////////////// ВЫБРАТЬ Справочник1.Ссылка КАК Ссылка ИЗ Справочник.Справочник1 КАК Справочник1 ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ИСключаемые КАК ВТ_ИСключаемые ПО (ВТ_ИСключаемые.Ссылка= Справочник1.Ссылка) ГДЕ ВТ_ИСключаемые.Ссылка ЕСТЬ NULL | |||
| 12
    
        Kassern 06.12.22✎ 16:43 | 
        (11) ПОМЕСТИТЬ ВТ_ИСключаемые - не бесплатная операция     | |||
| 13
    
        Ryzeman 06.12.22✎ 16:50 | 
        (8) Какой ты вредный) Да, нормально, так работают запросы. Если ты хочешь выбрать что то в одной таблице чего нет в другой - тебе в любом случае надо их связывать, ничего наркоманского в этом нет. (4) так вообще ровно то же самое что ты в (6) написал, только с учётом рекомендаций 1с из
 https://its.1c.ru/db/metod8dev/content/2499/hdoc /dooshneela mode off | |||
| 14
    
        1Сергей 06.12.22✎ 17:15 | 
        (8) >>а наркоманские связи в (0),(1) и (4) это будто нормально?
 стесняюсь спросить. А что в Вашем понимании ненаркоманские связи? | |||
| 15
    
        Said_We 06.12.22✎ 18:15 | 
        (0) "но если не ни одного документа, то не выводится ничего, а должно выводиться все "
 Неа - не должно. Вы прицепляете к пустому множеству что-то слева. Так как множество пустое, то на выходе будет пустое множество. Если будет декартово перемножение, то эффект будет тот же, так как умножение любого множества с пустым множеством даёт пустое множество. Правильный ответ в (6) Только я не понял зачем там условие "И НЕ Справочник1.ПометкаУдаления". В задаче такого не было. Все так все. Условие "IN (SELECT)" И "NOT IN (SELECT)" по скорости очень разные. Первое в разы быстрее, так как проверяется на первое вхождение, а во втором случае проверяются все элементы. | |||
| 16
    
        Курцвейл 06.12.22✎ 18:15 | 
        (12) Все зависит от размера справочника. Если он большой, то (11) выгоднее. Если маленький то выгодно (1)     | |||
| 17
    
        Курцвейл 06.12.22✎ 18:17 | 
        (15) вложенные запросы это зло. Надо себя к этому приучать.     | |||
| 18
    
        Said_We 06.12.22✎ 18:17 | 
        (16) Предположу что (1) будет быстрее, так как не создается временная таблица. Она и не нужна.     | |||
| 19
    
        Курцвейл 06.12.22✎ 18:21 | 
        я тоже ошибся. правильнее так: 
 ВЫБРАТЬ Документ1.Реквизит1 КАК Ссылка ПОМЕСТИТЬ ВТ_ИСключаемые ИЗ Документ.Документ1 КАК Документ1 ИНДЕКСИРОВАТЬ ПО Ссылка; //////////////////////// ВЫБРАТЬ Справочник1.Ссылка КАК Ссылка ИЗ Справочник.Справочник1 КАК Справочник1 ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ИСключаемые КАК ВТ_ИСключаемые ПО (ВТ_ИСключаемые.Ссылка= Справочник1.Ссылка) ГДЕ ВТ_ИСключаемые.Ссылка ЕСТЬ NULL | |||
| 20
    
        Said_We 06.12.22✎ 18:21 | 
        (17) Чем это зло вложенные запросы? Если вложенный запрос к большой физической таблице, то ...
 (1) "ЛЕВОЕ СОЕДИНЕНИЕ Документ.Документ1 КАК Документ1" Как раз правильнее переписать на вложенный запрос, что бы JOIN с большой таблицей не делать. (выбрать различные т.Реквизит1 ИЗ Документ.Документ1 КАК т) | |||
| 21
    
        Курцвейл 06.12.22✎ 18:24 | 
        (20) От вложенных запросов может Оптимизатор забалдеть. Или по крайней мере долго думать.     | |||
| 22
    
        Said_We 06.12.22✎ 18:24 | 
        (19) Ага у тебя 100500 документов с 1000 строк в каждой, а в справочнике всего 1500 элементов. Представь сколько ты запихаешь строк во временную таблицу и потом это ещё джойнить будешь. Не верно.     | |||
| 23
    
        Курцвейл 06.12.22✎ 18:26 | 
        (22) Значит надо еще агрегировать временную таблицу. Зато я буду всегда с индексом. Сканить всю таблицу документов все равно придется.
 А твоим вложенным мы еще будем сканить всю таблицу справочника | |||
| 24
    
        Said_We 06.12.22✎ 18:27 | 
        (23) Правильный ответ в (6). Только условие на пометку удаления убрать - в условии задачи её нет.     | |||
| 25
    
        Said_We 06.12.22✎ 18:31 | 
        Почти правильный в (1) если свернуть предварительно таблицу как в (20) написано. Если так сделать то (1) и (6) дадут по скорости примерно одинаковый результат.     | |||
| 26
    
        vis_tmp 06.12.22✎ 18:41 | 
        Однозначно, вариант (6).     | |||
| 27
    
        Said_We 06.12.22✎ 18:41 | 
        (23) "А твоим вложенным мы еще будем сканить всю таблицу справочника" - с какого перепуга. первое что выполняется это FROM. Если во FROM вложенный запрос, то будет выполняться сначала он.
 Если вложенный запрос выполняется в километровом тексте запроса миллион раз, то это зло с точки зрения сопровождения и внесения в него изменений. Нужно найти эти все вложения. + Если этот вложенный запрос не простой а к нескольким таблицам и долгий по времени выполнения, то правильнее один раз его результат куда-то во временную таблицу и пихнуть. Если запрос к физическим таблицам и НЕТ сложных соединений, например в веде сравнения на больше и меньше у полей, по которым нет индекса, то быстрее будет обращение к физическим таблицам. Сам по себе подзапрос "select ... from (select...)" достаточно недорого стоит по времени. | |||
| 28
    
        Курцвейл 07.12.22✎ 15:50 | 
        (27) Это не так. Почитайте требование к запросу для динамического списка. Если станет понятно почему так рекомендовано не использовать подзапросы, то можно дальше копнуть, чтобы понять что подзапросы это зло. И чем лучше использование временных таблиц. 
 С другой стороны как ведь все происходит - вот тут подзапрос, там подзапрос и пошло поехало. Тем самым набивается рука на плохих практиках. | |||
| 29
    
        Said_We 07.12.22✎ 15:52 | 
        (28) При чем тут динамический список и запрос?     | |||
| 30
    
        Said_We 07.12.22✎ 16:01 | 
        (29) "Тем самым набивается рука на плохих практиках." - главное определить, что есть плохо и что есть хорошо.
 Когда подзапросы применять правильно, а когда нет я выше написал. Бывают ситуации, когда временные таблицы это зло. Так что и их не применять? Конечным критерием является скорость работы и затрачиваемые ресурсы. В каждой конкретной задаче на каждой конечной базе можно получать совсем разные результаты. Что оптимальнее тут и сейчас, то и применяют. Как пример, если в задаче подобной задаче в (0) с 100500 документами по 1000 строк в каждом, то применять внутренние таблицы может оказаться злом. Представьте что у вас справочник в 20 000 объектов и вам необходимо найти пяток элементов, которые не используются. т.е. во внутреннюю таблицу вам необходимо помещать почти весь справочник. Так зачем это делать, если вы его из физической таблицы и так почти весь достаёте? | |||
| 31
    
        lodger 07.12.22✎ 16:01 | 
        (29) без него не получится оправдать наркотрип.     | |||
| 32
    
        Said_We 07.12.22✎ 16:23 | 
        (31) Не понятно только зачем оправдывать.
 Берешь большую базу торговли и какой-нибудь документ или сразу регистр и номенклатуру. Делаешь запрос с временной таблицей и без. Смотришь результат по времени. Удивляешься почему пусть 50% времени уходит на создание временной таблицы. Берешь маленькую базу, или ту же базу, но не с номенклатурой, а с мелким справочником или таблицей, и видишь практически одинаковый результат. Долго думаешь. Динамический список, СКД.... работают с запросом как с источником данных и делают они это как-то по своему. Там могут быть другие результаты. | 
| Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |