1с что приоритетнее и или

Обновлено: 05.07.2024

Эффективные условия запросов

Область применения: управляемое приложение, мобильное приложение, обычное приложение.

1. Условия запросов должны быть написаны оптимально с точки зрения производительности, чтобы исключить существенное увеличение длительности выполнения запросов при увеличении объема данных в таблицах.

Поля основного условия в секциях ГДЕ, ПО и виртуальных таблицах должны быть проиндексированы. Основное условие может быть уточнено дополнительным условием, но объединять их следует только по И.

Важно понимать структуру индексов, которые получаются при индексировании полей и учитывать их при построении основного условия (см. Индексы таблиц базы данных, Несоответствие индексов и условий запроса). Например, при индексировании разных полей одного объекта метаданных создаются разные индексы, а не один в который помещаются все проиндексированные поля и использоваться основным условием будет только один из них.

Основное условие – это то, что позволяет ограничить объем выборки больше других условий и его составляющие объединены по И.

Дополнительное условие – это то, что объединено с основным условием по И и его составляющие могут быть любой сложности (НЕ, <>, +, -, /, *, функции и т.п.).

Основное условие должно содержать только такие операции, которые позволяют выполнять поиск по индексу:

  • для первого и всех используемых полей индекса, кроме последнего, только = и И;
  • для последнего или единственного используемого поля индекса допустимо использовать =, >, <, >=, <=, ПОДОБНО, МЕЖДУ, В, ИЛИ (приводимое к В);
  • нельзя использовать арифметические операции, функции, отрицания и неравенства.

Для условий в ГДЕ или в виртуальной таблице следует индексировать поля в основной таблице, из которой выполняется выборка.

Для условий в ПО ЛЕВОГО соединения следует индексировать поля в правой таблице.

Для условий в ПО ВНУТРЕННЕГО соединения следует индексировать поля в таблице с большим количеством записей.

Основное условие желательно строить таким образом, чтобы оно использовало индексы, которые автоматически создает платформа.

1.1. Описанные выше требования допустимо не соблюдать, если в таблицах, из которых выполняется выборка, или с которыми выполняется соединение, всегда будет мало данных (менее 1000 записей) или запросы с такими условиями выполняются очень редко.

1.2. Если записей в таблице много и выполнить указанные выше требования невозможно, то можно попробовать:

  • преобразовать условия (см. п. 3, п. 4);
  • добавить в таблицу заранее вычисляемые индексированные поля, которые заполняются при записи в нее и используются вместо сложного условия;
  • если указанные выше рекомендации не помогли, то следует пересмотреть архитектуру решения так, чтобы можно было выполнить эти условия.

2.1. В основном условии оператор ИЛИ можно использовать только для последнего из используемых или единственного поля индекса, когда оператор ИЛИ можно заменить на оператор В.

ГДЕ
Таблица.Поле = &Значение1
ИЛИ Таблица.Поле = &Значение2

т.к. можно переписать при помощи оператора В (специально переписывать не нужно, можно оставить, как есть):

ГДЕ
Таблица.Поле В (&Значения)

ГДЕ
Таблица.Поле1 = &Значение1
ИЛИ Таблица.Поле2 = &Значение2

нельзя переписать при помощи "В", но можно переписать при помощи "ОБЪЕДИНИТЬ ВСЕ" (каждое поле Поле1 и Поле2 должны быть проиндексированы):

ГДЕ
Таблица.Поле1 = &Значение1

ГДЕ
Таблица.Поле2 = &Значение1

Примечание: заменить ИЛИ на ОБЪЕДИНИТЬ ВСЕ можно не всегда, убедитесь, что результат будет действительно тем же, что и при ИЛИ, перед тем, как применять.

2.2. В дополнительном условии оператор ИЛИ можно использовать без ограничений.

ГДЕ
Таблица.Поле1 = &Значение1 // Основное условие (использует индекс)
И // Дополнительное условие (можно использовать ИЛИ)
(Таблица.Поле2 = &Значение2 ИЛИ Таблица.Поле3 = &Значение3)

ГДЕ
(Таблица.Поле1 = &Значение1 ИЛИ Таблица.Поле1 = &Значение2)
И
(Таблица.Поле2 = &Значение3 ИЛИ Таблица.Поле2 = &Значение4)

т.к. можно переписать при помощи В (специально переписывать не нужно, можно оставить, как есть):

ГДЕ
Таблица.Поле1 В (&Значения1) // Основное условие
И Таблица.Поле2 В (&Значения2) // Дополнительное условие (или наоборот)

3. Оператор ПОДОБНО

В основном условии для последнего из используемых или единственного поля индекса можно использовать оператор ПОДОБНО. Функции работы со строками, в некоторых случаях, можно привести к оператору ПОДОБНО и использовать его в основном условии.

ГДЕ
ПОДСТРОКА(Таблица.Поле, 1, 6) = "строка"

ГДЕ
Таблица.Поле ПОДОБНО "строка%"

ГДЕ
ПОДСТРОКА(Таблица.Поле, 3, 6) = "строка"

ГДЕ
Таблица.Поле ПОДОБНО "__строка%" // Литерал не должен начинаться с символов "_" или "%"

Добавить новое вычисляемое при записи в таблицу поле, которое будет содержать фрагмент ПОДСТРОКА(Таблица.Поле, 3, 6). Проиндексировать это поле и искать по следующему условию:

ГДЕ
Таблица.ВычисляемоеПоле ПОДОБНО "строка%"

4. Оператор МЕЖДУ

В основном условии для последнего из используемых или единственного поля индекса можно использовать оператор МЕЖДУ. Функции работы с датой, в некоторых случаях, можно привести к оператору МЕЖДУ и использовать его в основном условии.

ГДЕ
МЕСЯЦ(Таблица.Поле) = 1

ГДЕ
Таблица.Поле МЕЖДУ &ДатаНачалаМесяца И &ДатаКонцаМесяца

Например, ДатаНачалаМесяца=01.01.2016, ДатаКонцаМесяца=31.01.2016 23:59:59

5. Выражение ВЫБОР

Выражение ВЫБОР можно использовать только в дополнительных условиях.

ГДЕ
Таблица.Поле1 = &Значение1 // Основное условие (использует индекс)
И // Дополнительное условие (можно использовать ВЫБОР)
ВЫБОР
КОГДА Таблица.Поле2 = &Значение2
ТОГДА Таблица.Поле3 = &Значение3
ИНАЧЕ Таблица.Поле4 = &Значение4
КОНЕЦ

ГДЕ
ВЫБОР // Основное условие (поиск по индексу использоваться не будет)
КОГДА Таблица.Поле2 = &Значение2
ТОГДА Таблица.Поле3 = &Значение3
ИНАЧЕ Таблица.Поле4 = &Значение4
КОНЕЦ

6. Арифметические операции

Арифметические операции над полями можно выполнять только в дополнительных условиях.

ГДЕ
Таблица.Поле1 = &Значение1 // Основное условие (использует индекс)
И // Дополнительное условие (можно выполнять арифметические операции)
Таблица.Поле2 - 1 > 0

ГДЕ
Таблица.Поле1 - 1 > 0 // Основное условие (поиск по индексу невозможен)

7. Если в конфигурации описано несколько ролей с разным ограничением доступа на уровне записей (RLS), то не следует назначать одному пользователю более одной такой роли. Если один пользователь будет включен, например, в две роли с RLS - бухгалтер и кадровик, то при выполнении всех его запросов к их условиям будут добавляться условия обоих RLS с использованием логического ИЛИ. Таким образом, даже если в исходном запросе нет условия ИЛИ, оно появится там после добавления условий RLS. Такой запрос так же может выполняться неоптимально - медленно и с избыточными блокировками.

вот такой запрос. проблема в условиях с субконто : если субконто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. Встаем на первую открывающую скобку и с помощью сочетания клавиш CTRL+] находим тело первого узла и переносим целиком в одну следующую строку с отступом относительно слова Если

2. Следующий логический оператор будет И или ИЛИ. Он и определяет тип группы этого уровня при условии что все группы обрамлены скобками. Для повышения наглядности вставляем в начало группы операцию с не нарушающим результат вычисления группы константным значением. Для И это будет ИСТИНА, а для ИЛИ это будет ЛОЖЬ. ИСТИНА не меняет результат конъюнкции (ИСТИНА И), и ЛОЖЬ не меняет результат дизъюнкции (ЛОЖЬ ИЛИ). Рассмотрим преобразование выражения примера к И-ИЛИ дереву.

3. Встаем на следующую открывающую скобку корневого уровня и повторяем шаг 1.

4. Слово Тогда для наглядности я переношу на отдельную строку с тем же отступом, что и Если, а все внутренние строки условия имеют больший отступ. Таким образом мы четко обозначаем начало и конец условия.

5. Далее повторяем шаги 1-3 для всех вложенных узлов (условий в скобках). Следует заметить, автор оригинального выражения не все группы обрамил скобками и последние 2 оператора из числа образующих группы различны и не разделены скобками. В итоге получаем

6. Теперь нам становится понятно, что логическое выражение можно упростить. Все вложенные однотипные (И или ИЛИ) группы можно смело всегда поднимать в родительскую группу.

7. В таком виде уже можно довольно безопасно убрать скобки вокруг условий внутри строк. В итоге получаем

Кажется, что в итоге получилось заметно более простое и наглядное выражение. В исходном выражении было 16 скобок, в преобразованном - всего 2.

По идее, как изначально оформлять логические выражение по этой методике уже должно быть понятно.

Хочу обратить ваше внимание на отсутствие унарной операции НЕ как типа группы. При желании конечно можно было бы ввести в методику и группу НЕ, но она слишком отличается от рассмотренных и я лично сторонник обходить ее стороной и опускать на самые нижние узлы.

Думаю, что эту методику можно успешно применять не только к встроенному языку 1С, но и многим другим языкам.

Использую эту методику уже много лет.

Плюсы:

- повышает наглядность выражения после некоторого привыкания
- облегчает рефакторинг, т.к. позволяет четко видеть пути упрощения (устранения избыточности) выражения
- облегчает отладку, т.к. позволяет быстро комментировать(выключать)/раскомментировать(включать) фрагменты выражения
- облегчает изменение порядка фрагментов выражения
- позволяет дописывать комментарии к каждому узлу дерева
- сокращает левые отступы, вложенность условий, количество строк в коде по сравнению с некоторыми другими подходами

Минусы:

- не все сразу понимают чисто оформительское назначение "Истина И" и "Ложь Или"
- уходит больше времени на начальное написание выражения
- выражение занимает большее число строк
- часто не оправдывает себя в простых выражениях
- автоформатирование кода выравнивает все строки условия по одной границе

Шаблоны

Для удобства написания сложных логических выражений по этой методике рекомендую добавить себе шаблоны

Читайте также: