Где выбор когда 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
"
Эти операторы возможно использовать во всех 4 ситуациях, но контекст (окружаемые переменные у них отличаются).
В первых двух случаях условия накладываются на поля выборки, например:
ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты КАК СпрКонтрагенты ГДЕ СпрКонтрагенты.ИНН<>""
Обращение идет через имя таблицы (в простых запросах может опускаться, но в сложных может вызывать неоднозначность поля).
Данное условие вызывает ограничение выборки (обычно уменьшает ее)
В конструкторе запроса находятся на вкладке условия:
В произвольном варианте пишется текстом, в обычном выбирается поле, оператор сравнения и значение:
ВЫБОР КОГДА
Этот условный оператор используется для преобразования значения, ограничивает же выборку только когда расположен после служебного слова ГДЕ.
Допустимо несколько подчиненных условий. Может находится в полях выборки, полях условий ГДЕ, группировок, итогов (универсальный оператор для сложных условий)
Например, так выглядит вариант преобразования:
ВЫБРАТЬ
ВЫБОР
КОГДА 1 = 2
ТОГДА "Никогда не будет истиной"
КОГДА 1 = 1
ТОГДА "Всегда будет истиной"
ИНАЧЕ ДАТАВРЕМЯ(1, 1, 1)
КОНЕЦ КАК ПолеПредставленияЗначения
Вариант использования в условии ГДЕ, результат выборки должен возвращать булево значение либо сравниваться с чем-то еще
Пример № 1
ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты КАК К ГДЕ ВЫБОР КОГДА К.ИНН = "" ТОГДА ЛОЖЬ ИНАЧЕ ИСТИНА КОНЕЦ
Пример № 2:
ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты КАК К ГДЕ ВЫБОР КОГДА К.ИНН = "" ТОГДА "" ИНАЧЕ "Заполнено" КОНЕЦ = "Заполнено"
Параметры виртуальных таблиц
В данном случае оперирование идет с полями таблиц, например ресурсами, измерениями, реквизитами. В этих условиях обращение идет без точки (контекст этого не требует).
ВЫБРАТЬ * ИЗ РегистрСведений.КурсыВалют.СрезПоследних(, Валюта.Код = "RUR")
В конструкторе запроса они находятся вот здесь:
Стоит отметить, что обычно используется ограничение над измерениями, так как иначе условие отнесется к выборке для получения, а не на сам результат (на ресурсы ограничения следует наложить в операторе ГДЕ, чтобы получить ожидаемый результат).
Накладывание условия в запросе на измерения, если нет обращения через точку (как в примере выше), ускоряет выборку: на больших таблицах, это будет визуально заметно; на небольших можно использовать как удобно.
ИМЕЮЩИЕ
Для наложения отбора для результата «группировочных» функции
ВЫБРАТЬ
Контрагенты.ИНН,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Контрагенты.Ссылка) КАК Ссылка
ИЗ
Справочник.Контрагенты КАК Контрагенты
СГРУППИРОВАТЬ ПО
Контрагенты.ИНН
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Контрагенты.Ссылка) > 1 И
Контрагенты.ИНН <> ""
В данную выборку попадут дубли ИНН, когда оно вообще заполнено.
В конструкторе запроса также находится на вкладке условия
В этой конструкции также возможно использование «группировочных» операторов И,ИЛИ, но сравнивать можно с константами запроса, с функцией или значением, входящим в группировку (другие реквизиты справочника в данном примере не будут доступны для сравнения -> тогда следует использовать ГДЕ).
Люди кончают самоубийством оттого, что получают по почте одну рекламу.
— Фредерик Бегбедер
При работе с языком запросов 1С, иногда возникает ситуация, когда требуется проверить выражение, является ли оно ЛОЖЬ или Истина. В случае положительного результата присвоить ему значение выражения для замены.
Конструкция оператора ВЫБОР
Несколько примеров
Пример №1
Есть таблица «Таблица1», в которой перечислены все дни с понедельника по воскресенье.
ДеньНедели |
Понедельник |
Вторник |
Среда |
Четверг |
Пятница |
Суббота |
Воскресенье |
Необходимо, для строк со значениями «Суббота» и «Воскресенье» в отдельном поле указать, что это выходной. Во всех остальных случаях, рабочий день. Реализуем поставленную задачу в виде запроса к исходной таблице.
Текст запроса может выглядеть так:
ВЫБРАТЬ
ДеньНедели,
ВЫБОР
КОГДА ДеньНедели =»Суббота »
ИЛИ ДеньНедели = «Воскресенье »
ТОГДА «Выходной»
ИНАЧЕ «Рабочий день»
КОНЕЦ КАК ВидДня
ИЗ
Таблица1. ДеньНедели КАК ДеньНедели
ДеньНедели | ВидДня |
Понедельник | Рабочий день |
Вторник | Рабочий день |
Среда | Рабочий день |
Четверг | Рабочий день |
Пятница | Рабочий день |
Суббота | Выходной |
Воскресенье | Выходной |
В данном примере, используя оператор ВЫБОР, мы перебираем все строки из «Таблица1». Параллельно проверяя каждую на соответствие условию.
КОГДА ДеньНедели =»Суббота »
ИЛИ ДеньНедели = «Воскресенье «
Если сработает одно из них, то в колонку «ВидДня» произойдёт запись выражения замены, расположенного после ключевого слова ТОГДА. Во всех остальных случаях будет записано выражение расположенное после слова ИНАЧЕ. Причём если убрать секцию ИНАЧЕ, программа примет такую конструкцию и не выдаст ошибку. Однако если проверяемое выражение вернёт ЛОЖЬ, тогда строки, в которые должно было подставится выражение замены, получать значение NULL. Рассмотрим подробнее подобную ситуацию.
Пример №2
Возьмём уже известную нам таблицу из первого примера.
ДеньНедели |
Понедельник |
Вторник |
Среда |
Четверг |
Пятница |
Суббота |
Воскресенье |
Получите понятные самоучители по 1С бесплатно:
Необходимо вывести в отдельную таблицу количество выходных дней. Причём информацию о количестве рабочих дней, будем считать излишней. Для наглядности решим задачу в несколько этапов. За основу возьмём запрос из примера №1. Уберём из него секцию ИНАЧЕ, а поле для вывода оставим только то, которое получаем конструкцией оператора ВЫБОР.
ВЫБРАТЬ
ВЫБОР
КОГДА ДеньНедели =»Суббота »
ИЛИ ДеньНедели = «Воскресенье »
ТОГДА «Выходной»
КОНЕЦ КАК ВидДня
ИЗ
Таблица1. ДеньНедели КАК ДеньНедели
Из результата запроса видно, что все строки, не вошедшие в условие после ключевого слова КОГДА получили . Как известно это отсутствие значения. Таким образом, нам остаётся только сгруппировать полученную таблицу. Применив к группировке агрегатную функцию КОЛИЧЕСТВО ( ).
Текст запроса может выглядеть так:
ВЫБРАТЬ
КОЛИЧЕСТВО(ВЫБОР
КОГДА ДеньНедели =»Суббота »
ИЛИ ДеньНедели = «Воскресенье »
ТОГДА «Выходной»
КОНЕЦ) КАК ВидДня
ИЗ
Таблица1. ДеньНедели КАК ДеньНедели
В заключении хочется сказать, что оператор ВЫБОР хоть и не часто находит свое применение при написании запросов в 1С, но в некоторых ситуациях является незаменимым инструментом для разработчика.
Войдите как ученик, чтобы получить доступ к материалам школы
Язык запросов 1С 8.3 для начинающих программистов: условный оператор
Автор уроков и преподаватель школы: Владимир Милькин
Условный оператор в запросе
Давайте напишем запрос, который получает названия и калорийность еды:
А теперь добавим в результат запроса колонку, в которую будем выводить жирность еды по следующим правилам:
- если калорийность меньше 100, то жирность низкая;
- если калорийность от 100 до 200, то жирность нормальная;
- если калорийность больше 200, то жирность высокая.
Как этого можно добиться, ведь в таблице Справочник.Еда нет колонки Жирность?
Оказывается, эту колонку мы можем добавить сами, используя условный оператор внутри запроса:
Давайте внимательнее присмотримся к тексту запроса:
В секции ВЫБРАТЬ идёт перечисление полей выборки: Наименование, Калорийность, а затем вместо третьего поля идёт конструкция условного оператора, результат которого и попадает в третью колонку.
Условия оператора обрабатываются последовательно . Если одно из них оказалось верным, то в качестве результата возвращается соответствующее значение. Если же ни одно из условий не выполнилось, то возвращается значение из секции ИНАЧЕ. Если же ни одно из условий не выполнилось, и в операторе отсутствует секция ИНАЧЕ, то возвращается значение NULL (о нём мы поговорим в одном из следующих уроков).
Поэтому новый запрос вернёт такую таблицу:
Отступление
Обратите внимание, что третья колонка в таблице, которую вернул запрос, называется Поле1. Это имя было сгенерировано системой автоматически, потому что третьей колонке не соответствует никакого реального поля в таблице Справочник.Еда, откуда можно было бы это имя получить.
Но в наших силах дать ей это имя. Для этого сразу после описания поля нужно написать ключевое слово КАК, а после этого через пробел указать само имя. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Такое имя будет называться псевдонимом поля .
Псевдонимы можно присваивать любым полям, в том числе тем, у которых уже есть имя. Давайте сделаем псевдоним Еда для поля Наименование:
Но вернёмся к условному оператору в запросах.
Более сложные логические выражения в условиях оператора
В логических условиях оператора выбора можно использовать и более сложные выражения.
Пример использования логического оператора ПОДОБНО:
Пример использования функции ПОДСТРОКА:
Более сложные результаты условного оператора
Конечно, результатом условного оператора может быть не только константная строка, но и любое другое выражение, допустимое в запросе.
Войдите как ученик, чтобы получить доступ к материалам школы
Язык запросов 1С 8.3 для начинающих программистов: условия
Автор уроков и преподаватель школы: Владимир Милькин
Условия в запросах
Давайте напишем запрос, который запрашивает из таблицы Справочник.Еда наименование еды, её цвет, вкус и калорийность:
Секция ГДЕ
А теперь давайте сделаем, чтобы вернулась еда только жёлтого цвета. Делается это при помощи секции ГДЕ в которой необходимо задать условие отбора:
В нашем случае таким условием будет равенство реквизита Цвет (а вернее его свойства Наименование) строковому значению "Жёлтый" ( через ё ):
В результате запрос вернёт нам только строки с едой, у которой реквизит Цвет установлен в Жёлтый:
Таким образом, секция ГДЕ позволяет задать условия отбора данных из таблиц. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Если задана секция ГДЕ , то в запросе обрабатываются только те строки таблиц, для которых условие секции оказывается истинным.
Обратите внимание, что поля, которые участвуют в условии (в нашем случае поле Цвет) не обязаны входить в список выбираемых полей:
В данном случае реквизит Цвет участвует в условии (секция ГДЕ ), но не участвует в списке выбираемых полей (секция ВЫБРАТЬ ):
Условие отбора может определяться и как простое логическое выражение , и как более сложное , в котором простые логические выражения соединяются между собой логическими операторами И, ИЛИ, НЕ.
Для примера, давайте выберем еду, у которой цвет белый или калорийность больше 100:
Секция ИМЕЮЩИЕ
Если в запросе используется группировка (см. предыдущий урок) и мы хотим наложить условие на результаты группировки, секция ГДЕ не подойдёт. Вместо неё нужно использовать секцию ИМЕЮЩИЕ .
Давайте подсчитаем суммарную калорийность еды по цветам. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Для этого используем группировку по цвету и агрегатную функцию СУММА по калорийности:
А теперь наложим условие на результат группировки так, чтобы остались только цвета с суммарной калорийностью больше 100:
Таким образом, секция ИМЕЮЩИЕ позволяет накладывать условия на значения агрегатных функций при группировке.
Обратите внимание, что агрегатные функции, которые участвуют в условии (в нашем случае поле СУММА(Калорийность)) не обязаны входить в список выборки:
В данном случае агрегатная функция СУММА(Калорийность) участвует в условии (секция ИМЕЮЩИЕ), но не участвует в списке выборки (секция ВЫБРАТЬ):
Условие отбора секции ИМЕЮЩИЕ может также определяться и как простое логическое выражение , и как более сложное , в котором простые логические выражения соединяются между собой логическими операторами И, ИЛИ, НЕ.
Для примера, давайте выберем цвета, имеющие суммарную калорийность больше 200 И меньше 300:
Читайте также: