1с что приоритетнее и или
Простенький вопросик для знатоков от зрителей :)
Почему настоятельно не рекомендуется использовать оператор ИЛИ в условии запроса?
(ЗаявкаНаОтгрузкуНакладные.ВидНакладной = "ЗТО" И ЗаявкаНаОтгрузкуНакладные.Накладная.Отправитель = &Отправитель)
Не следует использовать ИЛИ в секции ГДЕ запроса. Это может привести к тому, что СУБД не сможет использовать индексы таблиц и будет выполнять сканирование, что увеличит время работы запроса и вероянтность возникновения блокировок. Вместо этого следует разбить один запрос на несколько и объединить результаты.
Например, запрос
(11) Ха ха. то есть сервер 1С должен был сам заменить запрос на объединение? а если там более одного ИЛИ? )))
Можно подумать что сервер такой глупый, что всегда будет строить не оптимальный план. Но сложные случаи возможно ему нужно помочь.
(9) Классические пример:
a) Кривости RTFM от 1С.
б) Варианта, когда использование ИЛИ безопасно.
в) Шаблонности м ы шления 1С ников.
(8) Все ему понятно.
Посмотрит статистику и какой-нибудь использует.
(8) Можно твое имя и фамилию, пожалуйст. Для летописи.
(23) Ходят упорные слухи, что там где оптимизатор MS SQL еще справляется (хотя и без гарантии) оптимизаторы других СУБД (включая Oracle) впадают в ступор. Возможны и обратные случаи, но авторы типовых и прочих тиражируемых решений сидят на MS SQL, поэтому такие проблемы нетипичны.
(29) А в 1С хотят, чтобы работало на всех поддерживаемых СУБД более менее прилично. Поэтому выдвигают рекомендации писать запрос так, чтобы самый негодный оптимизатор справлялся удовлетворительно, а не только самый годный в случае если повезет.
(30)
То есть нельзя никому верить, Печенкин Роман.
Надо все проверять, ставить под сомнение и пытаться докопаться до сути.
Как бы тебя не слепил красный кожаный, блестящий на солнце, плащъ.
(33) Ну я как бэ согласен, хорошо.
Но хотелось бы некоторого веса словам.
А то получается, Рупасов сказал А, ты сказал Б.
Но Рупасов все-таки сказал на ИТС всей России, а ты на МиСте узкому кругу.
Спрашивается, как решить, кто прав, кто нет.
Может, моделирование ситуации решит спор? :))
(22) б - если условия на поля составного типа, то план запроса действительно может отличаться эпическим образом. Даже со всеми возможными ВЫРАЗИТЬ. Проверено на себе.
(43) Планы НИКОГДА не бывают нелогичными и не вылезают ВНЕЗАПНО. Всегда есть причина, по которой sql выбрал этот план, надо просто долго ковырять.
(45) Он может не ошибаться, а добросовестно заблуждаться. Причина разумеется будет, только станет ли лучше от этого результат?
"result (cost=0.00..4.08 rows=1 width=19) (actual time=0.000..0.000 rows=0 loops=1)
one-time filter: false
-> index only scan using _docum10341_bydocnum_sr on Документ.XXXXXXXXXX t1 (cost=0.00..4.08 rows=1 width=19) (never executed)
total runtime: 0.018 ms
"limit (cost=0.00..4.09 rows=1 width=0) (actual time=0.023..0.023 rows=0 loops=1)
-> index scan using pg_class_relname_nsp_index on pg_class (cost=0.00..4.09 rows=1 width=0) (actual time=0.022..0.022 rows=0 loops=1)
filter: (pg_table_is_visible(oid) and (relkind = 'r'::""char""))
total runtime: 0.040 ms
"
"bitmap heap scan on Документ.XXXXXXXXXX t1 (cost=4.15..8.11 rows=2 width=19) (actual time=1.536..1.539 rows=2 loops=1)
recheck cond: ((Номер = '000000011'::mvarchar) or (Номер = '000000010'::mvarchar))
-> bitmapor (cost=4.15..4.15 rows=2 width=0) (actual time=1.530..1.530 rows=0 loops=1)
-> bitmap index scan on _docum10341_bydocnum_sr (cost=0.00..2.07 rows=1 width=0) (actual time=1.517..1.517 rows=1 loops=1)
index cond: (Номер = '000000011'::mvarchar)
-> bitmap index scan on _docum10341_bydocnum_sr (cost=0.00..2.07 rows=1 width=0) (actual time=0.012..0.012 rows=1 loops=1)
index cond: (Номер = '000000010'::mvarchar)
total runtime: 1.560 ms
"
"limit (cost=2.10..9.61 rows=1 width=0) (actual time=0.037..0.037 rows=0 loops=1)
-> bitmap heap scan on pg_class (cost=2.10..9.61 rows=1 width=0) (actual time=0.036..0.036 rows=0 loops=1)
rows removed by filter: 2
-> bitmap index scan on pg_class_relname_nsp_index (cost=0.00..2.10 rows=4 width=0) (actual time=0.010..0.010 rows=7 loops=1)
index cond: (relname = 'tt35'::name)
total runtime: 0.054 ms
"
"result (cost=0.00..8.15 rows=2 width=19) (actual time=0.040..0.051 rows=2 loops=1)
-> append (cost=0.00..8.15 rows=2 width=19) (actual time=0.040..0.051 rows=2 loops=1)
-> index only scan using _docum10341_bydocnum_sr on Документ.ХХХХХХХХХХ t1 (cost=0.00..4.08 rows=1 width=19) (actual time=0.039..0.039 rows=1 loops=1)
heap fetches: 1
-> index only scan using _docum10341_bydocnum_sr on Документ.ХХХХХХХХХХ t2 (cost=0.00..4.08 rows=1 width=19) (actual time=0.010..0.010 rows=1 loops=1)
total runtime: 0.079 ms
"
Логические выражения – выражения, содержание знаки логических операций и подчиняющихся при вычислении логическим правилам. Результатом таких операций является одно из значений: логическая истина или логическая ложь.
Логические выражения используются в качестве условий управляющих операторов языка.
Во встроенном языке определено два вида логических операций:
-
– операции сравнения двух значений простых типов; – операции над логическими значениями по правилам булевой алгебры;
Операции сравнения
Операция | Описание |
---|---|
> | Строго больше |
>= | Больше, либо равно |
= | Равно |
<> | Не равно |
Строго меньше | |
Меньше, либо равно |
Все операции сравнения определены для операндов совпадающих простых типов.
Операции сравнения «Равно» и «Не равно», кроме того, определены для значений агрегатных (составных) типов, т.е. их можно использовать для сравнения двух объектов встроенного языка, содержащих ссылку на объект базы данных.
Булевы операции
Операция | Operation | Описание |
---|---|---|
НЕ | NOT | Логическое отрицание |
И | AND | Логическое умножение |
ИЛИ | OR | Логическое сложение |
Приоритет выполнения логических операций
При вычислении логических выражений программа руководствуется приоритетом логических операций (в порядке убывания):
Для того, чтобы повлиять на порядок вычислений можно использовать круглые скобки.
Внимание!
Круглые скобки крайне необходимы в том случае, когда вы используете несколько операций сравнения в одном логическом выражении! Иначе, вы получите синтаксическую ошибку «Неправильное использование арифметической или строковой операции»
В сложных логических выражениях нередко самому автору спустя какое-то время тяжело разобраться, не говоря уже о других программистах. Предлагаемая методика позволяет повысить наглядность таких выражений путем оформления в виде И-ИЛИ дерева и одновременно выполнять их рефакторинг.
Возьмем для примера фрагмент кода из типовой бухгалтерии
Не правда ли от количества скобок "рябит в глазах"? Конечно скобки иногда необходимы для расстановки последовательности вычисления, но записывая их линейно в таком количестве мы заметно усложняем восприятие (читаемость) выражения.
Приоритеты логических операций
Для начала вспомним приоритеты логических операций. Сначала выполняется Не, потом И и затем Или. Скобки традиционно имеют наивысший приоритет выполнения и гарантируют порядок выполнения вложенных в них операций. Однако их избыточное применение создает продемонстрированные в примере трудности. Зачастую скобки ставят лишь для того, чтобы перестраховаться в сложных и плохо читаемых логических выражениях.
Методика И-ИЛИ дерева
Я же предлагаю сложные логические выражения оформлять в виде И-ИЛИ дерева. Под И-ИЛИ деревом я подразумеваю дерево, нетерминальные узлы которого представляют собой группы (последовательности) одинаковых логических операций И или ИЛИ, а терминальные - остальные логические выражения. Хорошим примером такого дерева является отбор настроек компоновки данных, правда у него верхняя (корневая) группа всегда имеет тип "И". В случае встроенного языка мы этим не ограничены и можем использовать любой тип верхней группы. В рассмотренном примере как раз сверху расположена группа "ИЛИ".
1. Встаем на первую открывающую скобку и с помощью сочетания клавиш CTRL+] находим тело первого узла и переносим целиком в одну следующую строку с отступом относительно слова Если
2. Следующий логический оператор будет И или ИЛИ. Он и определяет тип группы этого уровня при условии что все группы обрамлены скобками. Для повышения наглядности вставляем в начало группы операцию с не нарушающим результат вычисления группы константным значением. Для И это будет ИСТИНА, а для ИЛИ это будет ЛОЖЬ. ИСТИНА не меняет результат конъюнкции (ИСТИНА И), и ЛОЖЬ не меняет результат дизъюнкции (ЛОЖЬ ИЛИ). Рассмотрим преобразование выражения примера к И-ИЛИ дереву.
3. Встаем на следующую открывающую скобку корневого уровня и повторяем шаг 1.
4. Слово Тогда для наглядности я переношу на отдельную строку с тем же отступом, что и Если, а все внутренние строки условия имеют больший отступ. Таким образом мы четко обозначаем начало и конец условия.
5. Далее повторяем шаги 1-3 для всех вложенных узлов (условий в скобках). Следует заметить, автор оригинального выражения не все группы обрамил скобками и последние 2 оператора из числа образующих группы различны и не разделены скобками. В итоге получаем
6. Теперь нам становится понятно, что логическое выражение можно упростить. Все вложенные однотипные (И или ИЛИ) группы можно смело всегда поднимать в родительскую группу.
7. В таком виде уже можно довольно безопасно убрать скобки вокруг условий внутри строк. В итоге получаем
Кажется, что в итоге получилось заметно более простое и наглядное выражение. В исходном выражении было 16 скобок, в преобразованном - всего 2.
По идее, как изначально оформлять логические выражение по этой методике уже должно быть понятно.
Хочу обратить ваше внимание на отсутствие унарной операции НЕ как типа группы. При желании конечно можно было бы ввести в методику и группу НЕ, но она слишком отличается от рассмотренных и я лично сторонник обходить ее стороной и опускать на самые нижние узлы.
Думаю, что эту методику можно успешно применять не только к встроенному языку 1С, но и многим другим языкам.
Использую эту методику уже много лет.
Плюсы:
- повышает наглядность выражения после некоторого привыкания
- облегчает рефакторинг, т.к. позволяет четко видеть пути упрощения (устранения избыточности) выражения
- облегчает отладку, т.к. позволяет быстро комментировать(выключать)/раскомментировать(включать) фрагменты выражения
- облегчает изменение порядка фрагментов выражения
- позволяет дописывать комментарии к каждому узлу дерева
- сокращает левые отступы, вложенность условий, количество строк в коде по сравнению с некоторыми другими подходами
Минусы:
- не все сразу понимают чисто оформительское назначение "Истина И" и "Ложь Или"
- уходит больше времени на начальное написание выражения
- выражение занимает большее число строк
- часто не оправдывает себя в простых выражениях
- автоформатирование кода выравнивает все строки условия по одной границе
Шаблоны
Для удобства написания сложных логических выражений по этой методике рекомендую добавить себе шаблоны
вот такой запрос. проблема в условиях с субконто : если субконто1 счета равен значению в реквизите Субконто1 то нужно выводить эту строчку. либо всё выдает. и нужное не нужное. или ничего. никак не могу сообразить. помогите!
"ВЫБРАТЬ
| ВложенныйЗапрос.Период,
| ВложенныйЗапрос.Регистратор,
| ВложенныйЗапрос.СчетДт,
| ВложенныйЗапрос.СубконтоДт1,
| ВложенныйЗапрос.СубконтоДт2,
| ВложенныйЗапрос.СубконтоДт3,
| ВложенныйЗапрос.СчетКт,
| ВложенныйЗапрос.СубконтоКт1,
| ВложенныйЗапрос.СубконтоКт2,
| ВложенныйЗапрос.СубконтоКт3,
| ВложенныйЗапрос.Организация,
| СУММА(ВложенныйЗапрос.Сумма) КАК Сумма,
| ВложенныйЗапрос.Содержание
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(&Начало, &Окончание, ) КАК ХозрасчетныйДвиженияССубконто,
| (ВЫБРАТЬ
| ХозрасчетныйДвиженияССубконто.Период КАК Период,
| ХозрасчетныйДвиженияССубконто.Регистратор КАК Регистратор,
| ХозрасчетныйДвиженияССубконто.СчетДт КАК СчетДт,
| ВЫБОР
| КОГДА ХозрасчетныйДвиженияССубконто.СчетДт = &Счет
| И ХозрасчетныйДвиженияССубконто.СубконтоДт1 = &Субконто1
| ТОГДА ХозрасчетныйДвиженияССубконто.СубконтоДт1
| ИНАЧЕ НЕОПРЕДЕЛЕНО
| КОНЕЦ КАК СубконтоДт1,
| ВЫБОР
| КОГДА ХозрасчетныйДвиженияССубконто.СчетДт = &Счет
| И ХозрасчетныйДвиженияССубконто.СубконтоДт2 = &Субконто2
| ТОГДА ХозрасчетныйДвиженияССубконто.СубконтоДт2
| ИНАЧЕ НЕОПРЕДЕЛЕНО
| КОНЕЦ КАК СубконтоДт2,
| ВЫБОР
| КОГДА ХозрасчетныйДвиженияССубконто.СчетДт = &Счет
| И ХозрасчетныйДвиженияССубконто.СубконтоДт3 = &Субконто3
| ТОГДА ХозрасчетныйДвиженияССубконто.СубконтоДт3
| ИНАЧЕ НЕОПРЕДЕЛЕНО
| КОНЕЦ КАК СубконтоДт3,
| ХозрасчетныйДвиженияССубконто.СчетКт КАК СчетКт,
| ВЫБОР
| КОГДА ХозрасчетныйДвиженияССубконто.СчетКт = &Счет
| И ХозрасчетныйДвиженияССубконто.СубконтоКт1 = &Субконто1
| ТОГДА ХозрасчетныйДвиженияССубконто.СубконтоКт1
| ИНАЧЕ НЕОПРЕДЕЛЕНО
| КОНЕЦ КАК СубконтоКт1,
| ВЫБОР
| КОГДА ХозрасчетныйДвиженияССубконто.СчетКт = &Счет
| И ХозрасчетныйДвиженияССубконто.СубконтоКт2 = &Субконто2
| ТОГДА ХозрасчетныйДвиженияССубконто.СубконтоКт2
| ИНАЧЕ НЕОПРЕДЕЛЕНО
| КОНЕЦ КАК СубконтоКт2,
| ВЫБОР
| КОГДА ХозрасчетныйДвиженияССубконто.СчетКт = &Счет
| И ХозрасчетныйДвиженияССубконто.СубконтоКт3 = &Субконто3
| ТОГДА ХозрасчетныйДвиженияССубконто.СубконтоКт3
| ИНАЧЕ НЕОПРЕДЕЛЕНО
| КОНЕЦ КАК СубконтоКт3,
| ХозрасчетныйДвиженияССубконто.Организация КАК Организация,
| ХозрасчетныйДвиженияССубконто.Сумма КАК Сумма,
| ХозрасчетныйДвиженияССубконто.Содержание КАК Содержание
| ИЗ
| РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто КАК ХозрасчетныйДвиженияССубконто
| ГДЕ
| ((НЕ ХозрасчетныйДвиженияССубконто.СубконтоДт1 = НЕОПРЕДЕЛЕНО ////ТУТ ПРОБЛЕМА
| Или НЕ ХозрасчетныйДвиженияССубконто.СубконтоДт2 = НЕОПРЕДЕЛЕНО
| Или НЕ ХозрасчетныйДвиженияССубконто.СубконтоДт3 = НЕОПРЕДЕЛЕНО)
| И (не ХозрасчетныйДвиженияССубконто.СубконтоКт1 = НЕОПРЕДЕЛЕНО
| Или не ХозрасчетныйДвиженияССубконто.СубконтоКт2 = НЕОПРЕДЕЛЕНО
| Или не ХозрасчетныйДвиженияССубконто.СубконтоКт3 = НЕОПРЕДЕЛЕНО))
| И (ХозрасчетныйДвиженияССубконто.Период МЕЖДУ &Начало И &Окончание
| И ХозрасчетныйДвиженияССубконто.Организация = &Организация)) КАК ВложенныйЗапрос ////ТУТ ПРОБЛЕМА
|ГДЕ
| ((не ХозрасчетныйДвиженияССубконто.СубконтоДт1 = НЕОПРЕДЕЛЕНО ////ТУТ ПРОБЛЕМА
| Или не ХозрасчетныйДвиженияССубконто.СубконтоДт2 = НЕОПРЕДЕЛЕНО
| Или не ХозрасчетныйДвиженияССубконто.СубконтоДт3 = НЕОПРЕДЕЛЕНО)
| И (не ХозрасчетныйДвиженияССубконто.СубконтоКт1 = НЕОПРЕДЕЛЕНО
| Или не ХозрасчетныйДвиженияССубконто.СубконтоКт2 = НЕОПРЕДЕЛЕНО
| Или не ХозрасчетныйДвиженияССубконто.СубконтоКт3 = НЕОПРЕДЕЛЕНО))
| И (ХозрасчетныйДвиженияССубконто.Период МЕЖДУ &Начало И &Окончание
| И ХозрасчетныйДвиженияССубконто.Организация = &Организация) ////ТУТ ПРОБЛЕМА
|
|СГРУППИРОВАТЬ ПО
| ВложенныйЗапрос.Организация,
| ВложенныйЗапрос.СчетДт,
| ВложенныйЗапрос.СубконтоДт1,
| ВложенныйЗапрос.СубконтоДт2,
| ВложенныйЗапрос.СубконтоДт3,
| ВложенныйЗапрос.СчетКт,
| ВложенныйЗапрос.СубконтоКт1,
| ВложенныйЗапрос.СубконтоКт2,
| ВложенныйЗапрос.СубконтоКт3,
| ВложенныйЗапрос.Регистратор,
| ВложенныйЗапрос.Период,
| ВложенныйЗапрос.Содержание"
Помогите пожалуйста, возникла такая проблема - через конструктор запросов создаю запрос, ставлю условие ((Реквизит1=Истина И Реквизит2=10) ИЛИ (Реквизит3=ЛОЖЬ)). Т.е. порядок вычисления условий ставлю собственный. Но когда нажимаю "Ok" в редакторе условия, он удаляет эти скобки, и при закрытии конструктора в сформированном тексте запросе скобок тоже нет. Как можно сделать так, чтобы скобки не пропадали?
(2) почему не влияют? Разве ((Условие1 И Условие2) ИЛИ (Условие3)) не отличается от ((Условие1) И (Условие2 ИЛИ Условие3)) и от (Условие1 И Условие2 ИЛИ Условие3).
Проблема в читабельности условия? Ну что ж. некоторые вещи сделаны, да, для повышенной соображалки, а не для обычных пользователей.
(0) тема ниочём. Если база не файловая, то базовод сам построит план выполнения запроса и на порядок указаный вами ему наплевать (и как правило он действительно лучше знает как выполнять запрос) и даже если вы уверены что можете сделать подсказку оптимизатору - из 1С это не работает.
(10) подождите,
так я и хочу написать (2+2)*2. А по итогу получается 2+2*2. Или условие "ИЛИ" в 1С вычисляется последним?
(12)
приоритет логических операций:
1 - НЕ, 2 - И, 3 - ИЛИ
как можно писать запросы не зная матчасти?
Конъю?нкция (от лат. conjunctio союз, связь) — логическая операция, по своему применению максимально приближенная к союзу «и». Синонимы: логи?ческое «И», логи?ческое умноже?ние, иногда просто «И».
Дизъю?нкция (лат. disjunctio — разобщение), логи?ческое сложе?ние, логи?ческое ИЛИ, включа?ющее ИЛИ; иногда просто ИЛИ — логическая операция, по своему применению максимально приближённая к союзу «или» в смысле «или то, или это, или оба сразу»[1].
Условия могут определяться и как более сложные логические выражения, где фигурируют простые логические выражения, соединенные между собой с помощью логических операторов И, ИЛИ, НЕ.
Логические операторы имеют приоритет:
Самый низкий приоритет у оператора ИЛИ.
В условиях сначала вычисляются простые логические выражения, затем операции НЕ, затем операции И, в последнюю очередь – операции ИЛИ. Для того, чтобы обеспечить другой порядок вычислений, можно использовать круглые скобки ().
© ООО "1С", 1996-2011. Все права защищены.
Читайте также: