|
Запросы в 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% времени уходит на создание временной таблицы. Берешь маленькую базу, или ту же базу, но не с номенклатурой, а с мелким справочником или таблицей, и видишь практически одинаковый результат. Долго думаешь. Динамический список, СКД.... работают с запросом как с источником данных и делают они это как-то по своему. Там могут быть другие результаты. |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |