Имя: Пароль:
1C
1С v8
Как работает этот запрос?
,
0 pavlushov
 
27.01.22
12:51
ВЫБРАТЬ
    СостоянияПредметовВзаимодействий.Предмет КАК Предмет
ИЗ
    РегистрСведений.СостоянияПредметовВзаимодействий КАК СостоянияПредметовВзаимодействий
ГДЕ
    ИСТИНА В
            (ВЫБРАТЬ ПЕРВЫЕ 1
                ИСТИНА
            ИЗ
                РегистрСведений.ПредметыПапкиВзаимодействий КАК ПредметыВзаимодействий
                    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЖурналДокументов.Взаимодействия КАК ЖурналДокументовВзаимодействия
                    ПО
                        ПредметыВзаимодействий.Предмет = СостоянияПредметовВзаимодействий.Предмет
                            И ПредметыВзаимодействий.Взаимодействие = ЖурналДокументовВзаимодействия.Ссылка
                            И ЖурналДокументовВзаимодействия.Ответственный = &Пар
            ГДЕ
                ЕСТЬNULL(ПредметыВзаимодействий.Рассмотрено, ЛОЖЬ) = &Пар2
                И ЕСТЬNULL(ПредметыВзаимодействий.РассмотретьПосле, ДАТАВРЕМЯ(1, 1, 1)) <= &Пар3)

Всем доброго дня. Наткнулся на такой запрос. Я конечно понимаю что таблица СостоянияПредметовВзаимодействий проверяет наличие записей для каждой своей строки выполняя запрос в условии "ГДЕ". Но как это работает? Почему при соединении таблиц ПредметыВзаимодействий и ЖурналДокументовВзаимодействия внезапно указывается условие соединения с таблицей СостоянияПредметовВзаимодействий? Как эта таблица вообще доступна в этой части запроса? Может быть есть где то объяснение как работают подобные запросы, с картинками и пояснениями? Просто складывается ощущение, что условие ГДЕ работает как соединение в данном случае, для каждой записи основной таблицы стыкуются записи таблицы расположенной в условии. Так и есть по сути?
1 acht
 
27.01.22
12:55
google://коррелированный+подзапрос
2 Курцвейл
 
27.01.22
12:59
Коррелированный подзапрос это какашка от которой надо избавляться как можно быстрее.
3 pechkin
 
27.01.22
13:01
(2) далеко не факт
4 acht
 
27.01.22
13:05
(2) Все врут
5 pavlushov
 
27.01.22
13:07
(1) спасибо!
6 pavlushov
 
27.01.22
13:22
Это что, получается запрос в цикле?
7 exwill
 
27.01.22
13:26
(6) Все так. Одно только дополнение.
Есть соединение, есть условие соединения и есть просто условие. Общее правило таково, что все условия следует указывать в условиях соединения но не в условиях. Потому что просто условия применяются уже к результату соединения таблиц. Если условие соединения перенести в конструкцию ГДЕ, тогда произойдет следующее. Все соединится со всем, т.е. ты получишь декартово произведение двух таблиц (тысяча записей умножить на тысячу записей рано миллион). И уже к этому распухшему результату будет применяться условие ГДЕ. Но внешне для внутреннего соединения результаты всегда будут одинаковы. Левое соединение при таком подходе превратится во внутреннее. И это еще одна причина, по которой условия соединения всегда указываются в конструкции ПО, но не в конструкции ГДЕ.
Однако. Есть один случай, когда нам именно постобработка и потребуется. Мы получили результат внешнего (обычно левого) соединения. А в нем могут быть значения типа NULL. И теперь мы хотим наложить фильтр на значения типа NULL (выбрать все, что NULL или все, что не NULL). И для этого мы используем конструкцию ГДЕ. Конструкция ПО нам тут не поможет. Обратите внимание все это касается только внешнего соединения. Для внутреннего продолжает действовать правило: все условия в ПО.
Так что ваша интуиция вас не обманула. Данный запрос составлен неграмотно.
8 rsv
 
27.01.22
13:44
(0) слово истина ? Замени на 1 и будет более понятно.
9 fisher
 
27.01.22
14:01
(6) Реальный план выполнения и так из одних циклов состоит. Чудес не бывает. А текст запроса - это не план выполнения, а декларация требуемого результата. Поэтому не надо на этом зацикливаться. Но на "логическом" уровне можно рассматривать это как "запрос в цикле", чтобы понимать какой будет в итоге результат.
10 Ёпрст
 
27.01.22
14:05
(2) жалко только, что в селект листе товарищи с Селезнёвки так его и не реализовали
11 arsik
 
гуру
27.01.22
14:06
(7) Мне кажется что планировщик скуля обнаруживает такие неоптимальные соединения и накладывает условие на соединение. Но правильно конечно в соединении указать.
12 fisher
 
27.01.22
14:07
(7) Какая многословная чушь.
13 arsik
 
гуру
27.01.22
14:08
+(11) Не планировщик, а оптимизатор.
14 exwill
 
27.01.22
14:11
(12) Внутреннее соединение видите? ГДЕ видите? По существу есть, что возразить?
15 Жан Пердежон
 
27.01.22
14:14
(0) условие в ГДЕ проверяется для каждой строки результирующей таблицы и было бы странно, если бы таблица "СостоянияПредметовВзаимодействий" была бы там не доступна
Как то работает - надо смотреть план запроса (ну и уметь читать его заодно)
16 Ёпрст
 
27.01.22
14:15
(14) в данном конкретном случае, от переноса условия в ГДЕ в секцию ПО план запроса не поменяется от слова совсем.
17 acht
 
27.01.22
14:18
(14)
Еще будучи ребенком
Я узнал один секрет
Как-то утром поделился
Мудростью со мною дед
18 exwill
 
27.01.22
14:19
(16) Но лучше все же писать грамотно. Хотя бы для того, чтобы не ломать голову: этот наш случай он "данный конкретный" или не "данный конкретный". Да и буквы экономятся. Как видите, во всех смыслах лучше
19 Жан Пердежон
 
27.01.22
14:20
(7) иногда лучше жевать...
для внутреннего соединения разницы-то как раз и нет: указывать условие в ПО или в ГДЕ
разницы нет ни для результата запроса, ни для плана выполнения, ни для времени
20 exwill
 
27.01.22
14:23
(19) Согласен. Сейчас все оптимизаторы такое исправляют. Но зачем делать ошибку?
21 fisher
 
27.01.22
14:28
(14) По существу не "все условия следует указывать в условиях соединения но не в условиях". В общем случае результат получится разный. И не стоит заниматься никакими предварительными фантазийными оптимизациями, исходя из воображаемых представлений о работе внутренних механизмов. План выполнения в общем случае не завязан намертво на декларацию результата. И если результат запроса не зависит от места размещения условия, то план выполнения может получиться или такой же или не менее эффективный. Естественно, не стоит явные условия соединения переносить в ГДЕ - это и читается хуже и затруднит работу оптимизатору, увеличивая вероятность построения неоптимального плана. На условия соединений много эвристик завязано.
Но общие правила написания запросов - следовать скорее читабельности текста декларации, чем каким-то своим фантазиям о том, как именно он будет выполняться. Особенно если это в ущерб читабельности. Только если точно знаешь, что делаешь и зачем.
Есть общие правила типа держать в голове, попадает условие в индекс или нет. Для тяжелых запросов стараться заменять ИЛИ в условиях на группировку объединений. Типа такого, но не глубже. Остальное - это уже удел тонких оптимизаций если действительно попадаешь на узкие места производительности. Но там возможно правильнее будет не запрос хитровывернуто переписывать, а архитектурные изменения внести.
22 Жан Пердежон
 
27.01.22
16:02
(20) Какую ещё ошибку? Никто ничего не исправляет. Это функционально одно и тоже, хоть бы стандарт заглянул
23 youalex
 
27.01.22
16:11
(18) В данном конкретном случае используется (как минимум) эмуляция exists (where 1 in (select  top 1 1))
А такое нагляднее размещать именно в where
24 pavlushov
 
27.01.22
16:18
(22) Что за стандарт? Где найти?
25 exwill
 
27.01.22
16:41
(23) Я про другое ГДЕ, которое внизу. К верхнему вопросов нет
26 rsv
 
27.01.22
19:33
(24) стандарт он один . Омериканцы придумали.
ANSI SQL. Как обычно все читабельнее на msdn применительно к  ms скуль.
Есть два вида языков, одни постоянно ругают, а вторыми никто не пользуется.