Не провоцируйте СКД, или пример "как не надо"

Пример того, что не нужно использовать в запросах, чтобы не провоцировать СКД.

В данной заметке разберём конкретный пример конструкции, которую лучше не использовать в запросах, чтобы не удивляться результату СКД.

 

СКД — это волшебная система. Каждый раз удивляемся, сколько можно сэкономить времени, с умом используя её возможности. Однако, как известно, есть у неё и разные «особенности». И их тоже лучше знать.

 

Возьмём, к примеру, такую ситуацию.

ВЫБРАТЬ
    Валюты.Ссылка КАК Ссылка,
    Валюты.Наименование КАК Наименование,
    Валюты.Код КАК Код,
    Валюты.Наименование = "" ИЛИ Валюты.Код = "" КАК ОшибкаЗаполнения
ИЗ
    Справочник.Валюты КАК Валюты

 

Есть справочник с наименованием и кодом. Мы хотим вывести его элементы. И по каждому выводим колонку «ОшибкаЗаполнения» (булево). Колонка будет содержать значение Истина, когда Наименование или Код пустое.

Результат выполнения:

Вроде всё хорошо. Но предположим, что нам нужно теперь в полученном отчёте вывести только те записи, у которых «Ошибка заполнения» = Нет.

Накладываем отбор и выводим:

Неожиданный результат, верно?

 

Но для начала на таком простом запросе лучше самому попробовать добавить условие отбора. Не будем сейчас соревноваться в красоте запроса, а просто представим себя на месте СКД. Как бы она подставила наш отбор «Ошибка заполнения» = Нет?

 

  1. Выносим поле в секцию ГДЕ:
    ГДЕ Валюты.Наименование = "" ИЛИ Валюты.Код = ""

  2. Оборачиваем в скобки:
    ГДЕ (Валюты.Наименование = "" ИЛИ Валюты.Код = "")

  3. Сравниваем с значением отбора:
    ГДЕ (Валюты.Наименование = "" ИЛИ Валюты.Код = "") = ЛОЖЬ

 

Получаем такой текст запроса. Это то, чего мы ожидаем увидеть от СКД.

 

ВЫБРАТЬ
    Валюты.Наименование КАК Наименование,
    Валюты.Код КАК Код,
    Валюты.Наименование = "" ИЛИ Валюты.Код = "" КАК ОшибкаЗаполнения
ИЗ
    Справочник.Валюты КАК Валюты
ГДЕ
    (Валюты.Наименование = "" ИЛИ Валюты.Код = "") = ЛОЖЬ

Теперь же нам нужно отловить «реальный» текст запроса. Для этого добавляем в наш отчёт кусочек примитивного кода:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

КомпоновщикМакета   = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки     = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.ПолучитьНастройки());
НаборДанных         = МакетКомпоновки.НаборыДанных.Получить(0);

КонецПроцедуры

 

Ставим точку останова в конце процедуры, запускаем отладчик, переоткрываем отчёт и снова формируем его с наложенным отбором «Ошибка заполнения» = Нет

 

В результате в переменной НаборДанных можно увидеть свойство «Запрос».

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

ВЫБРАТЬ
    Валюты.Наименование КАК Наименование,
    Валюты.Код КАК Код,
    Валюты.Наименование = "" ИЛИ Валюты.Код = "" КАК ОшибкаЗаполнения
ИЗ
    Справочник.Валюты КАК Валюты
ГДЕ
    (Валюты.Наименование = "" ИЛИ Валюты.Код = "" = ЛОЖЬ)

В чём ошибка?

 

Если вернуться к нашим шагам наложения условия, можно понять, что СКД пропустила шаг 2.

 

  1. Выносим поле в секцию ГДЕ:
    ГДЕ Валюты.Наименование = "" ИЛИ Валюты.Код = ""

  2. Оборачиваем в скобки:
    ГДЕ (Валюты.Наименование = "" ИЛИ Валюты.Код = "")

  3. Сравниваем с значением отбора:
    ГДЕ (Валюты.Наименование = "" ИЛИ Валюты.Код = "") = ЛОЖЬ

 

Выходит, что логика СКД была такая:

 

  1. Выносим поле в секцию ГДЕ:
    ГДЕ Валюты.Наименование = "" ИЛИ Валюты.Код = ""

  2. Сравниваем с значением отбора:
    ГДЕ Валюты.Наименование = "" ИЛИ Валюты.Код = "" = ЛОЖЬ

 

Однако, без оборачивания в скобки, СКД полностью меняет смысл условия. В результате мы и видим такой результат. В поле формула отрабатывает нормально, но вот фильтрация работает неверно.

Интересно, что если данное поле убрать из запроса и вынести в вычисляемые поля СКД, то такой ошибки не будет.

 

 

 

Но что, если вынести поле в вычисляемые для нас не выход? Всё просто, применяем другую конструкцию и вместо:

Валюты.Наименование = ""
ИЛИ Валюты.Код = "" КАК ОшибкаЗаполнения

пишем

ВЫБОР
   КОГДА Валюты.Наименование = "" ИЛИ Валюты.Код = ""
        ТОГДА ИСТИНА
   ИНАЧЕ ЛОЖЬ
КОНЕЦ КАК ОшибкаЗаполнения

Не так красиво, но зато теперь СКД точно не накосячит, ведь просто подставит сравнение к концу поля.

Возможно, Вам больше понравится иначе изменить условие запроса, но в данный момент это не принципиально. Главное, при написании подобных запросов помнить про эту «особенность». Ведь лучше не провоцировать СКД.

 

Замечено давненько. Но сейчас протестировано на платформах: 8.3.12.1595, 8.3.14.1779.

86 Comments

  1. VmvLer

    Я не понял где косячит СКД, как-то сумбурно написано.

    Условия в тесте статьи сами по себе кривоваты, да и использование

    ИЛИ в условиях я видел только в типовом коде современных конфигураций.

    Если запрос пишет человек с опытом, то никаких ИЛИ в запросе не будет.

    Reply ↓
  2. VmvLer

    Логически верным будет выражение поля

        ВЫБОР
    КОГДА Валюты.Наименование = «»
    ТОГДА ИСТИНА
    КОГДА Валюты.Код = «»
    ТОГДА ИСТИНА
    ИНАЧЕ ЛОЖЬ
    КОНЕЦ КАК ОшибкаЗаполнения
    

    т.к. первое условие выбора наиболее вероятно

    я не знаю кому приходит в голову такое выражение поля

    Валюты.Наименование = «» ИЛИ Валюты.Код = «» КАК ОшибкаЗаполнения

    ЗЫ: неполадка из ничего, никто так выражение поля не пишет — вы первый у кого я увидел такой нонсенс.

    СКД права, что дала по рукам.

    Reply ↓
  3. SeiOkami

    (1) это простейший пример того, когда СКД неверно накладывает отбор на поле.

    Приемлимость использования в запросах приставки ИЛИ — это другой вопрос. Но однозначно СКД должна корректно накладывать отбор, несмотря на религиозные предпочтения разработчика.

    Reply ↓
  4. SeiOkami

    (2) СКД не дала по рукам, а сломала запрос. Вы пытаетесь похвастаться праведностью своих запросов, а не вникать в суть проблемы.

    Reply ↓
  5. Wern03

    Причем тут ИЛИ. С тем же успехом можно поставить И и будет та же ошибка. Ошибка интересная, спасибо. возьму на заметку.

    Reply ↓
  6. echo77

    (0)Похоже на баг компоновщика макета СКД. В 1С уже написали?

    Reply ↓
  7. Mortum

    Если не ошибаюсь, то возможность писать такое условие в выбранных полях появилось в платформе не сразу. А в скд просто забыли этот случай обработать.

    Reply ↓
  8. Mortum

    (2) писать 7 строк вместо одной с точно таким же смыслом. Вам платят за объём кода?

    Reply ↓
  9. qwinter

    (9), (4) такой документированной возможности не было и нет. Логические операции нельзя использовать в выражениях. В документации черным по белому написано:

    Во многих конструкциях языка запросов могут использоваться выражения. Выражения языка запросов описываются следующим набором правил:

    <Выражение>

    <Разыменование поля> |

    <Агрегатная функция> |

    <Встроенная функция> |

    <Операция выбора> |

    <Приведение типа>[.<Разыменование поля>] |

    <Значение> |

    <Выражение> <Бинарная операция> <Выражение> |

    <Унарная операция> <Выражение> |

    ( <Выражение> )

    <Бинарная операция>

    + | — | * | /

    <Унарная операция>

    — | +

    Показать

    https://its.1c.ru/db/v8310doc#bookmark:dev:TI000000494

    Когда же 1Сники начнут ну хоть немного документацию читать.

    Reply ↓
  10. SeiOkami

    (11)

    В выражениях к значениям соответствующих типов могут применяться бинарные и унарные операции.

    Не вижу ни противоречий, ни запретов использования конструкции, ни предупреждений, что СКД их сломает. При этом в вычисляемых полях они обрабатываются без проблем.

    P.S.: Эта статья как раз и нужна для того, чтобы показать конструкцию, которую «не надо». Именно потому, что среднестатистический разработчик нигде не видел такого предупреждения, посему может наткнуться на особенность СКД уже в проде.

    Reply ↓
  11. qwinter

    (12)

    ни запретов использования конструкции

    лицензионное соглашение где запрещено использовать недокументированные возможности, как я понимаю вы тоже не читали?

    ни предупреждений

    предупреждение, что недокументированное использование функций будет отрабатывать неверно??? Вы сейчас серьезно?????? С таким подходом только к врачу… Очень жаль ваших клиентов.

    Reply ↓
  12. SeiOkami

    (13) вы пытаетесь привязаться к бумажкам, я же говорю, что обычному разработчику эта конструкция не покажется чем-то неизведанным и недокументированным. Простые логические операции. И программист может их использовать, не подозревая, что это приведёт к ошибке СКД. Мне, как автору статьи, важно донести эту особенность, а не решать, кто виноват.

    Reply ↓
  13. Lucifer93

    Автор, тут дело в том, что Вы показываете пример плохого кода и говорите, что СКД его неправильно обработала. Для того, чтобы демонстрировать ошибку СКД покажите пример хорошего кода, который СКД обработает неправильно и не будет никаких вопросов к Вам. Ждем от Вас пример хорошего кода, который СКД отработает неправильно.

    Reply ↓
  14. SeiOkami

    (14) независимо от оптимизированности запроса, СКД совершает ошибку. Читатель о ней теперь ознакомлен, и лишний раз подумает, прежде чем использовать конструкцию. У меня нет цели «заваливать» СКД.

    Reply ↓
  15. Lucifer93

    (16) «независимо от оптимизированности запроса» Вот эта фраза очень интересная у Вас получается. То есть давайте писать кривые запросы, а потом жаловаться, что программа не так их понимает?!

    Reply ↓
  16. SeiOkami

    (17) если писать неоптимальные запросы, и ожидать, что будет работать неоптимально

    Но здесь СКД совершает грубейшую ошибку. И это уж точно никто не ожидает.

    Reply ↓
  17. SeiOkami

    (19)вы приводите странный пример. Запрос вполне ясный. Возможно, он не так оптимизирован (хотя это максимально спорное утверждение). Но он верен и очевиден. И в статье расписано, как должен накладываться отбор. Более того, СКД сама его так и накладывает, когда используются вычисляемые поля. Но с тем же самым полем косячит, когда он в запросе. Очевидно, что это ошибка. И очевидно, что это нужно знать при разработке. Иначе можно напороться. И уже не важно будет, кто здесь виноват

    Reply ↓
  18. milanse

    Спасибо, хорошее замечание к работе СКД.

    Те кто говорят про или в условиях, вообще ничего не понимают?

    Reply ↓
  19. Evil Beaver

    (11)

    Когда же 1Сники начнут ну хоть немного документацию читать

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

    Reply ↓
  20. dhurricane

    (20)

    Но он верен

    Коллега, именно к этой фразе у Ваших оппонентов претензия. Он не неоптимизирован, он именно не верен с точки зрения документации к платформе. По приведенной ссылке явно указано, какие операции и над какими операндами можно выполнять в полях выборки. Сложение, вычитание и прочие арифметические операции, например, в этом списке есть, а вот логических — нет. Поэтому и следует делать вывод, что использование операции «ИЛИ» в поле выборки запроса без оператор «ВЫБОР» недопустимо.

    (11) Честно говоря, для меня также стало открытием, что использовать логические операторы в таком виде в секции «ВЫБРАТЬ» недопустимо. Я перечитал соответствующие разделы документации и для платформы 8.3.10, и для 8.3.14, и нигде не смог найти «разрешение» на использование оператора «ИЛИ». Почему открытие? Потому, что я хорошо помню, что где-то видел это самое «разрешение». И копнув глубже нашел его в списке изменений платформы 8.3.6:

    Реализована возможность использования логических выражений в описании поля выборки и в выражениях фильтрации результатов запроса (предложение ГДЕ).

    Данная возможность не предоставлялась.

    При необходимости использования логического выражения в описании поля выборки было необходимо использовать операцию выбора.

    Источник: https://dl03.1c.ru/content/Platform/8_3_14_1779/1cv8upd_8_3_14_1779.htm#b1d73456-26c0-11e4-98ab-e61f135f174b

    Далее идут ссылки на ИТС, где должно быть более подробно описано изменение, но ничего подобного в тексте узнать не удалось.

    Так что для меня теперь это открытый вопрос. Что это: ошибка в документации или неверная интерпретация нововведений в платформе?

    Reply ↓
  21. dhurricane

    (24) Запрета нет. Но приведен список операций, называемых бинарными.

    Reply ↓
  22. Lucifer93

    (21) Боюсь, что Вам нужно перечитать правила формирования запросов. Они отлично описаны в Настольная книга 1С:Эксперта по технологическим вопросам. 2 издание и там понятным языком объясняется почему использование ИЛИ в запросах является плохим.

    Reply ↓
  23. d4rkmesa

    Вот хохма, набежали свидетели «святого СКД». Сам не использую подобные конструкции, но тут очевидно, что СКД работает не совсем ожидаемым образом, скажем так — не самым очевидным. Впрочем, в консоли СКД результирующий запрос смотрится и исправить можно довольно быстро.

    Reply ↓
  24. toypaul

    Все каменты про — «пиши запросы правильно», «читай документацию» вроде как и верные, но к сути вопроса не имеют никакого отношения. суть вопроса в том, что в платформе косяк. нельзя писать ИЛИ — не давай писать. если даешь писать, обрабатывай правильно.

    книга про эксперта в ДАННОМ КОНКРЕТНОМ СЛУЧАЕ вообще не к месту упомянута. давайте будем везде запрещать писать ИЛИ — даже в справочниках где пара десятков записей. бред какой-то.

    Reply ↓
  25. d4rkmesa

    (26) Хватит бредить уже.

    Reply ↓
  26. srub

    У меня тоже есть пример, когда СКД отрабатывает не корректно есть запрос

    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    | РасчетыСЗаказчикамиОбороты.Организация,
    | РасчетыСЗаказчикамиОбороты.Заказчик,
    | РасчетыСЗаказчикамиОбороты.Менеджер,
    | РасчетыСЗаказчикамиОбороты.Гаражка КАК Гаражка,
    | СУММА(ЕСТЬNULL(РасчетыСЗаказчикамиОбороты.СуммаПриход, 0)) КАК ПоступлениеОтЗаказчика,
    | СУММА(ЕСТЬNULL(РасчетыСЗаказчикамиОбороты.СуммаРасход, 0)) КАК РасходПоЗаказчику
    |ПОМЕСТИТЬ ВТ1
    |ИЗ
    | РегистрНакопления.РасчетыСЗаказчиками.Обороты(&ДатаНачала, &ДатаОкончания, , ) КАК РасчетыСЗаказчикамиОбороты
    |
    |СГРУППИРОВАТЬ ПО
    | РасчетыСЗаказчикамиОбороты.Организация,
    | РасчетыСЗаказчикамиОбороты.Заказчик,
    | РасчетыСЗаказчикамиОбороты.Менеджер,
    | РасчетыСЗаказчикамиОбороты.Гаражка
    |
    |ИНДЕКСИРОВАТЬ ПО
    | Гаражка
    |;
    |
    |////////////////////////////////////////////////////////////­////////////////////
    |ВЫБРАТЬ
    | РасчетыСПеревозчикамиОбороты.Организация,
    | РасчетыСПеревозчикамиОбороты.Перевозчик,
    | РасчетыСПеревозчикамиОбороты.Гаражка КАК Гаражка,
    | РасчетыСПеревозчикамиОбороты.Менеджер,
    | СУММА(ЕСТЬNULL(РасчетыСПеревозчикамиОбороты.СуммаРасход, 0)) КАК ОплатаПеревозчику,
    | СУММА(ЕСТЬNULL(РасчетыСПеревозчикамиОбороты.СуммаПриход, 0)) КАК ПриходПоПеревозчику
    |ПОМЕСТИТЬ ВТ2
    |ИЗ
    | РегистрНакопления.РасчетыСПеревозчиками.Обороты КАК РасчетыСПеревозчикамиОбороты
    |
    |СГРУППИРОВАТЬ ПО
    | РасчетыСПеревозчикамиОбороты.Организация,
    | РасчетыСПеревозчикамиОбороты.Перевозчик,
    | РасчетыСПеревозчикамиОбороты.Гаражка,
    | РасчетыСПеревозчикамиОбороты.Менеджер
    |
    |ИНДЕКСИРОВАТЬ ПО
    | Гаражка
    |;
    |
    |////////////////////////////////////////////////////////////­////////////////////
    |ВЫБРАТЬ
    | ВТ1.Организация КАК Организация,
    | ВТ1.Заказчик,
    | ВТ1.Гаражка.СтавкаСЗаказчиком КАК СтавкаСЗаказчиком,
    | ВТ1.Гаражка.СрокОплатыОтЗаказчиком КАК СрокОплатыЗаказчиком,
    | ВТ2.Перевозчик,
    | ВТ1.Гаражка.СтавкаСПеревозчиком КАК СтавкаСПеревозчиком,
    | ВТ1.Гаражка.СрокОплатыПеревозчику КАК СрокОплатыПеревозчику,
    | ВТ1.Менеджер,
    | ВТ1.Гаражка КАК Гаражка,
    | ВТ1.ПоступлениеОтЗаказчика,
    | ВТ2.ОплатаПеревозчику,
    | ВТ1.ПоступлениеОтЗаказчика — ВТ2.ОплатаПеревозчику КАК ОплаченоИзСвоих,
    | ВТ1.Гаражка.СтавкаСЗаказчиком — ВТ1.ПоступлениеОтЗаказчика КАК ДолгЗаказчика
    |ИЗ
    | ВТ1 КАК ВТ1
    |  ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ2 КАК ВТ2
    |  ПО ВТ1.Гаражка = ВТ2.Гаражка
    |ГДЕ
    | ВТ1.ПоступлениеОтЗаказчика < ВТ2.ОплатаПеревозчику
    |
    |УПОРЯДОЧИТЬ ПО
    | Организация,
    | Гаражка»;
    

    Показать

    В консоли запросов за выбранный период 36 записей. А СКД выдает 6 записей.

    Reply ↓
  27. milanse

    (26) Не надо бояться, надо делать. Второе издание не читал, первое лежало на краю стола, не успел прочитать, кто-то упер. Буду благодарен за скриншот выделенного жирным шрифтом обведенного в рамочку предупреждения «НИКОГДА, СЛЫШИТЕ НИКОГДА НЕ ИСПОЛЬЗУЙТЕ СЛОВО ИЛИ В ЗАПРОСАХ».

    Reply ↓
  28. sergathome

    (27) тоже поржал. логика у ребят потрясающая — есть куча дерьма на лестнице в подъезде, на чердаке которого написано, что она там лежит и по лестнице не нужно ходить, хотя она есть… шиза, да и только. угага

    Reply ↓
  29. sergathome

    (28) это типичный ФМГ от долгого чтения 1Сной «документации». Простите, но без кавычек оно не работает. Тут целая секта таких фимозников обитает…

    Reply ↓
  30. unichkin

    (30) не понял, а зачем группировка и выражение isNULL в первых двух запросах? Это ж оборотные таблицы. В выходном запросе почему условие в секции где, а не в соединении?

    Почему-то никто не вспоминает про расширение языка запросов для системы компоновки данных, а ведь именно им управляются отборы.

    Запрос из статьи можно (нужно) описать так:

    ВЫБРАТЬ

    Валюты.Ссылка КАК Ссылка,

    Валюты.Наименование КАК Наименование,

    Валюты.Код КАК Код,

    Валюты.Наименование = «»

    ИЛИ Валюты.Код = «» КАК ОшибкаЗаполнения

    ИЗ

    Справочник.Валюты КАК Валюты

    {ГДЕ

    (Валюты.Наименование = «»

    ИЛИ Валюты.Код = «») КАК ОшибкаЗаполнения}

    Тогда в результате наложения отбора СКД вернет

    ВЫБРАТЬ

    Валюты.Наименование КАК Наименование,

    Валюты.Код КАК Код,

    Валюты.Наименование = «»

    ИЛИ Валюты.Код = «» КАК ОшибкаЗаполнения

    ИЗ

    Справочник.Валюты КАК Валюты

    ГДЕ

    (Валюты.Наименование = «»

    ИЛИ Валюты.Код = «») = &П

    ___

    Хочется здесь добавить — СКД классная штука, но как пользователю нужно понимать что программист лишь автоматизирует его труд, а не создает волшебные кнопки, так и программистам надо понимать что есть инструмент со своей спецификой, который как и многие другие инструменты не умеет вообще ВСЕ.

    Reply ↓
  31. Lucifer93

    (29)Отличный комментарий и ,главное, по делу и аргументированный.

    Reply ↓
  32. Lucifer93

    (31) «В секции ГДЕ логическое ИЛИ использовать тоже не рекомендуется. Следует разбить один запрос на несколько и объединить результаты (при возникновении проблем на данном участке кода). Пояснения — в этой же главе ниже.» Вот цитата, которая сохранена у нас для разработчиков, чтобы они не делали глупых ошибок.

    Reply ↓
  33. SeiOkami

    (36) откройте любую типовую и тыкайте пальцем в каждое использование ИЛИ в секции ГДЕ.

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

    Reply ↓
  34. sergathome

    (35) Первое реальное возражение. Да, ***, да, язык СКД ОТЛИЧАЕТСЯ от языка запросов ! В «документации » это звучит абсолютно невнятно и неудивительно, что возникают секты на этой почве. бгы

    Reply ↓
  35. Lucifer93

    (38) Так в данном случае Вы не используете их с умом. Вы просто пишите ерунду, которую Вам уже правили в постах выше. Я изначально попросил Вас написать качественно и найти ошибку. Никто не говорит, что СКД святая, я говорю Вам напишите запрос ПРАВИЛЬНО и тогда ошибка исчезнет. Вся статья, по сути, не будет иметь никакого смысла, если разработчик будь следовать элементарным правилам написания запроса(на данном этапе). Сделайте нормальный запрос, повторите ошибку и не будет к Вам вопросов.

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

    Reply ↓
  36. VmvLer

    (38) Дело не в ИЛИ или И.

    То что я написал в начале темы детализировано в (34)

    хватит бредить(с)

    Reply ↓
  37. SlavaKron

    (23) Судя по всему, 1С автоматически переделывает логические выражения в секции ВЫБРАТЬ в CASE структуру, потому что, например, в T-SQL нельзя использовать булево в выборке – оно не является типом данных.

    Reply ↓
  38. qwinter

    (23)

    Так что для меня теперь это открытый вопрос. Что это: ошибка в документации или неверная интерпретация нововведений в платформе?

    Нет никакого противоречия, логическое выражение это

    В языке запросов в операциях выбора и в условиях отборов используются логические выражения.

    <Логическое выражение>

    <Выражение> |

    (<Выражение> | <Логическое выражение>) <Операция сравнения> (<Выражение> | <Логическое выражение>) |

    <Выражение> [НЕ] В [ИЕРАРХИИ] (<Список значений>) |

    <Выражение> [НЕ] В [ИЕРАРХИИ](<Описание запроса>) |

    <Выражение> [НЕ] МЕЖДУ <Выражение> И <Выражение> |

    <Выражение> ЕСТЬ [НЕ] NULL |

    <Выражение> ССЫЛКА <Имя таблицы> |

    <Выражение> [НЕ] ПОДОБНО <Литерал типа СТРОКА>

    [СПЕЦСИМВОЛ <Литерал типа СТРОКА>]

    <Операция сравнения>

    > | < | = | >= | <= | <>

    <Список значений>

    <Выражение>[, <Выражение> [, …]]

    Логическим выражением может быть:

    ● обычное выражение языка запросов, если его результат имеет логический тип;

    ● операция сравнения двух выражений языка запросов; выполняется в соответствии с правилами сравнения значений, описанными в разделе «Правила сравнения значений»;

    ● оператор проверки совпадения/несовпадения значения выражения с одним из перечисленных или со значениями, содержащимися в результате другого запроса;

    ● оператор проверки вхождения значения выражения в диапазон;

    ● оператор проверки значения выражения на NULL;

    ● оператор проверки ссылочного значения выражения на ссылку на определенную таблицу;

    ● оператор проверки строкового значения наподобие шаблону.

    При сравнении значений используются правила сравнения значений, описанные ниже.

    Показать

    https://its.1c.ru/db/v8310doc#bookmark:dev:TI000000500

    Разрешения на использования логических операторов языка запросов в выражениях там нет.

    Reply ↓
  39. milanse

    Уже предлагали зарегистрировать баг ?

    Reply ↓
  40. pm74
    Валюты.Наименование = «» ИЛИ Валюты.Код = «»

    = НЕ (НЕ Список.Наименование = «» И НЕ Список.Код = «»)

    Reply ↓
  41. Evil Beaver

    (43) вот что вас так тянет язвить-то, а? Ведь специально для Вас написал, что знаю про то, что в грамматике И и ИЛИ названы отдельно. Нет, все равно вы мне тыркаете, что я ссылку не читал.. Я вообще-то промышленный парсер под язык запросов писал, и почти каждую продукцию грамматики помню безо всяких ссылок на ИТС. Будьте вежливее, пожалуйста.

    Reply ↓
  42. bulpi

    Критики этой статьи до боли напоминают мне работников техподдержки 1с (не только 1с, но мы сейчас здесь). Ты , значит, поработал для них бесплатным бета-тестером, нашел очевиднейший баг, не пожалел времени, задокументировал, пример написал, разжевал как для идиотов, написал туда … ИИИИ…. тебе отвечают, что ты сам дурак и читай документацию. Я вот так и бросил писАть в техподдержку.

    Люди, вы, блин, издеваетесь ? Если НЕЛЬЗЯ такое писАть в СКД, то нужно об этом выдавать диагностику на этапе перехода от текста запроса к полям. «Недопустимое логическое выражение в условии …» , как то так.

    Reply ↓
  43. surikateg

    (35)

    В СП написано:

    При автоматическом заполнении доступных полей запроса выполняются следующие действия:

    все поля списка выборки и их дочерние поля становятся доступными для выбора, упорядочивания, группировки, отбора и др.;

    Как программист должен догадаться о создании дополнительной конструкции ГДЕ в расширении языка запросов СКД?

    Reply ↓
  44. milanse

    Какой ужас, что же мы видим в центре внимания на главной странице инофостарта https://infostart.ru/public/1074066/ в перовом примере кода используется условие «или», а во втором выражение, которое может поломаться в СКД. Куда же смотрят тру программисты 1с, которые изучили настольные книги экспертов по технологическим вопросам ? Не время спать, 1с в опасности

    Reply ↓
  45. unichkin

    (50) Нажать «F1» и прочитать про язык расширений компоновки? Навскидку — еще можно поизучать типовые, посмотреть курсы, почитать книги… Суть-то не в СКД. Развиваться надо. Писать много кода, стараться делать это правильно (ИТС имею в виду, хоть обкидайтесь помидорами). Гугл + ИТС + здравый смысл в помощь.

    Reply ↓
  46. GreenDragon

    (38) А, так у вас эталоном являются типовые? Офигеть! Мы тут им баги репортим, а оно вон как! Вам написал уже не один человек про крайнюю нежелательность использования логического оператора «ИЛИ» в секции условий.

    Reply ↓
  47. GreenDragon

    (48) Тут просто автор заявляет, что

    …Важно понимать, что целью статьи не является классифицировать те или иные конструкции как «документированными» или же нет.

    И не решать, что использовать «хорошо», а что «плохо».

    А лишь показать пример, как реагирует СКД на данный вид конструкций.

    И при этом использует «ИЛИ» в секции условий. На не рекомендуемый вид конструкций СКД реагирует плохо. Вот прям в первом комментарии об этом написано, а потом ещё с десяток подобных комментариев, но автор упоролся упёрся и настаивает, вот все и нервничают, повышая градус неадекватности.

    Reply ↓
  48. surikateg

    (52)

    Я как раз и процитировал что по F1 написано. В каких курсах или книгах есть полное описание расширения языка запросов СКД? Гугл не 1с. Оптимальность кода это другой вопрос, синтаксис запроса корректен для платформы, он должен выполнятся правильно.

    Reply ↓
  49. unichkin

    (55)

    Я как раз и процитировал что по F1 написано. В каких курсах или книгах есть полное описание расширения языка запросов СКД? Гугл не 1с. Оптимальность кода это другой вопрос, синтаксис запроса корректен для платформы, он должен выполнятся правильно.

    В (50) вы утверждаете что это из СП. ctrl + shift + F1, если что. Полного — подозреваю, что ни в каких. Просто с опытом приходит понимание того, что такое СКД, и как с ним жить. И можно хоть 1000 статей написать на тему «вот так не работает!!», я как-то более практично привык смотреть на эту проблему. Хотя тоже много глючков переловил. Мир не идеален) Максимум что можно сделать — попробовать зарегистрировать багу через поддержку.

    По поводу синтаксиса — я бы вот не разделял понятия «синтаксис» и «оптимальность». Я бы объединил: все надо делать максимально просто, быстро и понятно. Попробуйте переписать ваш запрос, и посмотрите поймет ли его СКД после этого. Я понятия не имею чего там у платформы в мозгах, но подозреваю что писатели парсеров ориентировались на корректный входящий запрос, а не на то что их будут ловить подводными камнями.

    Reply ↓
  50. alex5550
    Если НЕЛЬЗЯ такое писАть в СКД, то нужно об этом выдавать диагностику

    Золотые слова…

    Reply ↓
  51. surikateg

    (56) В 1с и так язык запросов типа «sql» обрезан по самое не балуйся и давно уже не расширяется, в чем сложность написать нормальный парсер для СКД?

    Reply ↓
  52. VmvLer

    (49) (51)… вброшу еще на вентилятор

    Да забудьте вы про красную тряпку «ИЛИ» — оно тут не виновно и речь о нем шла в контексте. Еще раз суть:

    «Недопустимое логическое выражение в условии …»

    не надо нас, маленьких дурить, меняя контекст неполадки!

    в условии как раз допустимо выражение без КАК

    Валюты.Наименование = «» ИЛИ Валюты.Код = «» КАК ОшибкаЗаполнения
    

    а вот в выражении поля вместо логического выражения необходимо использовать

    Выбор …Когда.

    Это как таблица умножения и если вы забыли ИЛИ НЕ знали, что 2*2 = 4, то

    можно, конечно, строчить гневные петиции, мол, если я пишу 2*2 = 5, то пожалуйста сообщите мне почему так нельзя.

    Reply ↓
  53. unichkin

    (58) Это я думаю к техподдержке вопрос) Однако мне как программисту остается жить с тем, что есть.

    Reply ↓
  54. triviumfan

    Давно натыкался на сие поведение, ошибке уже 100500 лет.

    Reply ↓
  55. Evil Beaver

    (54) Как у вас всех так получается читать объяснения автора и в упор их не понимать…? Почему вы противопоставлете друг-другу тезисы «показать пример, как СКД реагирует» и «нельзя использовать ИЛИ»?? Это же несвязанные между собой вещи. Использование ИЛИ — иногда(!) ведет к плохому плану выполнения запроса. НО — операция ИЛИ это синтаксически корректная конструкция, ее в принципе можно применять.

    Далее, автор пишет, что можно написать вместо ИЛИ просто «И» и будет все равно ошибка. Никто это в упор не видит и начинает втирать, что ИЛИ неоптимально. Да, неоптимально. Но речь-то не об этом! Речь о том, что СКД, накладывая условие на поле, накладывает его не совсем ожидаемым образом.

    И да, это даже не ошибка СКД, в ее действиях есть логика, а для таких вещей надо применять вычисляемые поля или иные способы обхода (там же в статье).

    Но почему-то все считают, что корень всех бед статьи и ее автора — применение ИЛИ…

    Reply ↓
  56. Sashares

    (11)

    такой документированной возможности не было и нет. Логические операции нельзя использовать в выражениях

    Можно с 8.3.6.

    (11)

    Когда же 1Сники начнут ну хоть немного документацию читать.

    Действительно. Когда же начнут?

    (1) А вот то что СКД не корректно воспринимает условие, в дополнение к статье стоило бы написать на v8@1c.ru

    Reply ↓
  57. Sashares

    (62)

    И да, это даже не ошибка СКД, в ее действиях есть логика

    Нет в ней логики.

    Отбор накладывается по полю, а не по части поля.

    Почему СКД не знает о возможности использования логических выражениях в качестве полей, вопросы к Лейбовичу =)

    Reply ↓
  58. GreenDragon

    (62) Андрей, при всём моём уважении. Комментарий (14)

    Reply ↓
  59. dhurricane

    (63)

    Можно с 8.3.6.

    Чуть ниже я писал про это. Мне дали ответ, что в документации в отношении логических операций также отсутствует разрешение на использование бинарных операций «И/ИЛИ». Почитал документацию, оспорить не смог, стало быть ответ справедливый.

    Reply ↓
  60. GreenDragon

    (62) И ещё. Автор в конце как правильный рецепт предлагает вставлять инструкцию ВЫБОР. В секции ГДЕ. Угу. Дальше он предложит 2 раза в цикле запросы выполнять? Ненуачо, работает жи?

    Вопрос — если скормить условие вида: «НЕ (условие1 ИЛИ условие2)»?

    Reply ↓
  61. Sashares

    (66)

    Мне дали ответ, что в документации в отношении логических операций также отсутствует разрешение на использование бинарных операций «И/ИЛИ».

    Ох уж эти знатоки. Все то они знают.

    https://its.1c.ru/db/v836doc#bookmark:dev:TI000000464

    Reply ↓
  62. dhurricane

    (67) Не-не, там в пункте 8.2.17.1 дается определение «логической операции».

    Reply ↓
  63. spacecraft

    (69) а если так?

    Reply ↓
  64. dhurricane

    (70) Я описался комментарием выше. Речь была о «логических выражениях». На Вашем снимке, во-первых, речь про условия отбора, а не поля выборки. А во-вторых, в выделенном Вами тексте явно разделены понятия логического выражения и операторов «И/ИЛИ».

    Reply ↓
  65. spacecraft

    (71) читаем: «В простейшем случае условие является выражением, результат которого имеет значение логического типа. Логические выражения описаны в следующем разделе.

    Условия могут определяться и как более сложные логические выражения, где фигурируют простые логические выражения, соединенные между собой с помощью логических операторов И, Или, Не.»

    Про поля выборки, то там тоже упоминаются логические выражения. Так что актуально и для них.

    Reply ↓
  66. dhurricane

    (72) Извините, но не согласен. Условия — могут определяться и как более сложные логические выражения. Про поля выборки такое не сказано, следовательно определяться как более сложные, чем описано «в следующем разделе», они быть не могут.

    Я бы не хотел настаивать на точке зрения, что описанная в статье конструкция некорректна. Сам ею не раз пользовался и был уверен, что такой подход вполне допустим. Но после прочтения комментариев к настоящей статье сколько бы я ни вчитывался в документацию к платформе, я не смог разглядеть тому подтверждение. Опять же, я и не претендую на то, что всегда правильно могу прочитать и понять официальную документацию.

    Reply ↓
  67. spacecraft

    (73) хорошо. Далее:

    «Логическим выражением может быть:

    ● обычное выражение языка запросов, если его результат имеет логический тип»

    «Выражения языка запросов описываются следующим набором правил:

    <Разыменование поля> |

    <Агрегатная функция> |

    <Встроенная функция> |

    <Операция выбора> |

    <Приведение типа>[.<Разыменование поля>] |

    <Значение> |

    <Выражение> <Бинарная операция> <Выражение> |

    <Унарная операция> <Выражение> |

    ( <Выражение> )

    «

    Reply ↓
  68. dhurricane

    (74) А чуть ниже список бинарных операций, среди которых нет «И/ИЛИ»:

    + | – | * | /
    Reply ↓
  69. spacecraft

    (75) да, что-то не указано.

    Но все равно конструкция вида (<Логическое выражение> И <Логическое выражение>) это тоже логическое выражение.

    Reply ↓
  70. dhurricane

    (76) Конечно согласен. Но к сожалению, лишь на интуитивном уровне. Попробую, наверное, на днях «пошерстить» партнерский форум в поисках ответа, либо задать вопрос самому. Вдруг я не «утону в минусах», да еще и получу разъяснения сотрудников 1С. 🙂

    Reply ↓
  71. spacecraft

    (75) вот пример бинарной операции ИЛИ

    ВЫБРАТЬ
    ПриобретениеТоваровУслуг.Ссылка КАК Ссылка,
    ПриобретениеТоваровУслуг.Проведен
    И НЕ ПриобретениеТоваровУслуг.ПометкаУдаления КАК Актуально
    ИЗ
    Документ.ПриобретениеТоваровУслуг КАК ПриобретениеТоваровУслуг

    Вполне себе рабочая конструкция.

    Reply ↓
  72. Evil Beaver

    (65) При всем моем уважении, комментарий 14 нелогичен. Плохой запрос или хороший в данном случае роли не играет. Речь о необычном поведении СКД при использовании необычных полей, и только. Система должна иметь понятный набор поведений независимо от качества запроса. В данном случае СКД ведет себя не так, как вела бы с полем «ВЫБОР».

    Навскидку, попробуйте провести эксперимент не с ИЛИ, а просто с арифметическим выражением, например

    ВЫБРАТЬ ПолеРегистра + 2 КАК НаДваБольше

    и условие на это поле наложить.

    СКД отработает нормально или нет?

    Reply ↓
  73. dhurricane

    (78) Да, как я уже выше писал, сам использовал подобные конструкции, и осечек до сих пор не наблюдал.

    И простите за занудство, но Ваше выражение избыточно: документ не может быть одновременно проведен и помечен на удаление. Если, конечно, кто-то накануне не работал с БД напрямую.

    Reply ↓
  74. Evil Beaver

    (68) ВЫБОР в секции ГДЕ — ни разу не криминал. В типовых — полно такого. Зависит не от оператора ВЫБОР, а от того, что у него внутри. Если поле составного типа — то да, будет трэш.

    Reply ↓
  75. spacecraft

    (80) это всего лишь синтетический код для проверки работы бинарной операции ИЛИ. Ничего более.

    Reply ↓
  76. dhurricane

    (82) Еще раз простите, что не сдержался. 🙂

    Reply ↓
  77. spacecraft

    (80)

    документ не может быть одновременно проведен и помечен на удаление

    может 🙂

    «Если документ помечен на удаление, то не допускается выполнение проведения этого документа. Однако допускается наличие движений у документа, помеченного на удаление, так как в 1С:Предприятии 8 понятие проведенности документа не связано жестко с наличием движений.»

    Хотя это наверно не про флаг «Проведен».

    Reply ↓
  78. dhurricane

    (79) Эксперимент показал, что СКД отработает ровно также, как и в примере автора поста, т.е. добавит выражение поля в отбор как есть, без скобок. Но здесь нам на руку играет больший приоритет операции сложения.

    Reply ↓
  79. Evil Beaver

    (85) Спасибо! Что и требовалось доказать — оптимальность или неоптимальность запроса — это не то, что рассказывается в статье.

    Reply ↓
  80. GreenDragon

    (81) А индексы используются при такой конструкции?

    Я про вот это:

    https://its.1c.ru/db/v8std#content:658:hdoc

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

    Reply ↓
  81. Evil Beaver

    (87) Могут и использоваться. Зависит от того, что конкретно написано в ВЫБОР и от состава индекса.

    Reply ↓
  82. GreenDragon

    (88) У автора в секции ГДЕ используется вполне конкретное выражение. Автор использует оператор ВЫБОР в основном , а не в дополнительном условии Ниже скриншот, так я подозреваю, что вы не смотрели ссылку на стандарт.

    Reply ↓
  83. dhurricane

    (89) Я позволю себе встрять в Ваш диалог, извините. Уж очень интересно, какое альтернативное решение предложили бы Вы?

    Reply ↓
  84. Sashares

    (0)Для информации.

    В 8.3.16 исправили.

    Reply ↓
  85. Deslime

    Поржала с комментов — прям Священная Война Свидетелей Нуралиева ))

    Спасибо автору за статью — интересное замечание к работе СКД и пример хороший так как максимально очевидно показывает данный нюанс

    Reply ↓
  86. SlavaKron

    К черту скд. Товарщи, пишите кастомные отчеты.

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *