С удивлением обнаружил, что в запросах NULL не равен NULL
Ответы
В избранное
Подписаться на ответы
Сортировка:
Древо развёрнутое
Свернуть все
(1) newborn,
Это не новость, в описание 1с есть. Мол, любое сравнение на NULL вернет ЛОЖЬ
Для соединения используйте вариант:
Обратите внимание, что при отсутствие условия соединения значимых полей, т.е., в примере, без первого условия "ВТ_Первая.ПолеБезNULL=ВТ_Вторая.ПолеБезNULL", запрос вернет на каждое NULL из ВТ_Первая все записи из ВТ_Вторая, где ВТ_Вторая.ПолеNULL ЕСТЬ NULL.Произвойдет некое "умножение", если в обоих таблицах по 100 строк со значением NULL, то запрос вернет 10 000 строк
Это не новость, в описание 1с есть. Мол, любое сравнение на NULL вернет ЛОЖЬ
Для соединения используйте вариант:
ВЫБРАТЬ ВТ_Первая.Поле1,
ВТ_Вторая.Поле1
ИЗ ВТ_Первая как ВТ_Первая
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Вторая КАК ВТ_Вторая
ПО ВТ_Первая.ПолеБезNULL=ВТ_Вторая.ПолеБезNULL
И (ВТ_Первая.ПолеNULL ЕСТЬ NULL)
И (ВТ_Вторая.ПолеNULL ЕСТЬ NULL)
Обратите внимание, что при отсутствие условия соединения значимых полей, т.е., в примере, без первого условия "ВТ_Первая.ПолеБезNULL=ВТ_Вторая.ПолеБезNULL", запрос вернет на каждое NULL из ВТ_Первая все записи из ВТ_Вторая, где ВТ_Вторая.ПолеNULL ЕСТЬ NULL.Произвойдет некое "умножение", если в обоих таблицах по 100 строк со значением NULL, то запрос вернет 10 000 строк
(16)
с этими NULL всегда ставлю функции проверки ISNULL(<ЧтоТо>, 0) и с этим сравниваю. А вот теперь пошли "тяжелые задачи".
Ваш тест смотрю:
Выдает:
с этими NULL всегда ставлю функции проверки ISNULL(<ЧтоТо>, 0) и с этим сравниваю. А вот теперь пошли "тяжелые задачи".
Ваш тест смотрю:
ВЫБРАТЬ
1 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_Первая
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
3 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_ВТОРАЯ
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
ВТ_Первая.Поле1 КАК Поле1,
ВТ_Вторая.Поле1 КАК Поле11
ИЗ
ВТ_Первая КАК ВТ_Первая
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ВТОРАЯ КАК ВТ_Вторая
ПО ВТ_Первая.ПолеБезNULL = ВТ_Вторая.ПолеБезNULL
И (ВТ_Первая.ПолеNULL ЕСТЬ NULL)
И (ВТ_Вторая.ПолеNULL ЕСТЬ NULL)
ПоказатьВыдает:
Прикрепленные файлы:
(16) А так, умножение верно:
Код |
---|
ВЫБРАТЬ
1 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_Первая
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
10,
20,
NULL
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
3 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_ВТОРАЯ
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
11,
22,
NULL
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_Первая.Поле1 КАК Поле1,
ВТ_Вторая.Поле1 КАК Поле11
ИЗ
ВТ_Первая КАК ВТ_Первая
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ВТОРАЯ КАК ВТ_Вторая
ПО (ВТ_Первая.ПолеNULL ЕСТЬ NULL)
И (ВТ_Вторая.ПолеNULL ЕСТЬ NULL) Показать полностью |
Прикрепленные файлы:
(16) Речь, если сравнивать поле первой таблицы где одни NULL с полем другой таблицей где тоже есть NULL на равенство. И в запросе NULL <> NULL и будет ЛОЖЬ по соединению и получим при левом соединении отстуствие соединения таблиц (поле11 из второй таблицы где NULL).
Это если где-то NULL затесался в промежуточной таблице сложного запроса как реквизит через точку из пустой ссылки?
Вот что будет:
А при таком условии
все будет сравниваться, а без функции нет?
Мы получим верный результат, т.к. будут сравниваться 9999 и 9999 (главное уникальный признак поставить чтоб не было в полях сравниваемых таблиц иначе получим дубли.
А если таблицы тяжелые что делать? Как удобнее фильтровать? В промежуточных таблицах на условия типа "ГДЕ НЕ ВТ_Первая.ПолеNULL ЕСТЬ NULL" с выгрузкой в промежуточную таблицу? Или кодом прогонять таблицу значений, опять в запрос?
Это если где-то NULL затесался в промежуточной таблице сложного запроса как реквизит через точку из пустой ссылки?
ВЫБРАТЬ
1 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_Первая
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
10,
20,
NULL
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
3 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_ВТОРАЯ
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
11,
22,
NULL
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
ВТ_Первая.Поле1 КАК Поле1,
ВТ_Вторая.Поле1 КАК Поле11
ИЗ
ВТ_Первая КАК ВТ_Первая
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ВТОРАЯ КАК ВТ_Вторая
ПО ВТ_Первая.ПолеNULL = ВТ_Вторая.ПолеNULL
//(ВТ_Первая.ПолеNULL ЕСТЬ NULL)
// И (ВТ_Вторая.ПолеNULL ЕСТЬ NULL)
ПоказатьВот что будет:
А при таком условии
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ВТОРАЯ КАК ВТ_Вторая
ПО ISNULL(ВТ_Первая.ПолеNULL, 9999) = ISNULL(ВТ_Вторая.ПолеNULL, 9999)
все будет сравниваться, а без функции нет?
Мы получим верный результат, т.к. будут сравниваться 9999 и 9999 (главное уникальный признак поставить чтоб не было в полях сравниваемых таблиц иначе получим дубли.
А если таблицы тяжелые что делать? Как удобнее фильтровать? В промежуточных таблицах на условия типа "ГДЕ НЕ ВТ_Первая.ПолеNULL ЕСТЬ NULL" с выгрузкой в промежуточную таблицу? Или кодом прогонять таблицу значений, опять в запрос?
Точнее так - в SQL отсутствие значения является неопределенностью, которая не может быть равна ничему, в том числе и самой себе - настолько она неопределена :)
А в языках программирования бывает понятие математической неопределенности NaN, обладающее теми же свойствами.
А в языках программирования бывает понятие математической неопределенности NaN, обладающее теми же свойствами.
А вдруг вот это тоже удивит: :)
Если в запросе есть необходимость проанализировать значение некоторого выражения на равенство NULL, следует использовать не операции сравнения (=, <>), а специальный оператор проверки значения выражения на равенство NULL, имеющий следующий синтаксис:
<Выражение> ЕСТЬ [НЕ] NULL
Если в запросе есть необходимость проанализировать значение некоторого выражения на равенство NULL, следует использовать не операции сравнения (=, <>), а специальный оператор проверки значения выражения на равенство NULL, имеющий следующий синтаксис:
<Выражение> ЕСТЬ [НЕ] NULL
(9) Voffka,
Нет, я встретился с другой проблемой. У меня в запросе было левое соединение по полю, которое в обеих соединяемых таблицах было NULL. Я смотрю в регистр, в списке записей, вижу очевидное совпадение, а потом выполняю запрос - а связи нет.
Не сразу догадался, в чём проблема.
Нет, я встретился с другой проблемой. У меня в запросе было левое соединение по полю, которое в обеих соединяемых таблицах было NULL. Я смотрю в регистр, в списке записей, вижу очевидное совпадение, а потом выполняю запрос - а связи нет.
Не сразу догадался, в чём проблема.
С удивлением обнаружил, что запрос типа:
Вернет все элементы справочника
Запрос = Новый Запрос(
"ВЫБРАТЬ
| Контрагенты.Ссылка
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Ссылка В ИЕРАРХИИ(&КорневаяГруппа)"
);
Запрос.УстановитьПараметр("КорневаяГруппа", Справочники.Контрагенты.ПустаяСсылка());
ПоказатьВернет все элементы справочника
А еще, а еще!
Еще в 1С NULL в некоторых случаях физически содержится в полях данных.
Например, NULL записывается в те реквизиты элементов справочников, для которых в конфигураторе указано, что они доступны только для группы. И еще где-то, но я уже забыл :)
Еще в 1С NULL в некоторых случаях физически содержится в полях данных.
Например, NULL записывается в те реквизиты элементов справочников, для которых в конфигураторе указано, что они доступны только для группы. И еще где-то, но я уже забыл :)
Если уж пошли такие открытиях- то сам недавно обнаружил следующее (Это касается СКД)
Если в наборе данных использовать временные таблицы например одну по документам а одну виртуальной таблице регистра хозрасченый (например ХозрасчетныйОборотыДтКт)
И в таблице по документам использовать параметры &НачалоПериода, &КонецПериода а в таблице ХозрасчетныйОборотыДтКт в периодах использовать другие параметры для\ задания периода например
&НачалоПериодаДействи и &КонецПериодаДействия - то эти параметры будут игнорироваться системой и вместо них будет использоваться парfметры &НачалоПериода и &КонецПериода.
Я конечно понимаю что система сама создает для виртуальной таблицы хоз.расчетного регистра эти параметры (т.е. явно их можно не указывать) , но что бы так игнорировать указанные - для меня это было открытие
Если в наборе данных использовать временные таблицы например одну по документам а одну виртуальной таблице регистра хозрасченый (например ХозрасчетныйОборотыДтКт)
И в таблице по документам использовать параметры &НачалоПериода, &КонецПериода а в таблице ХозрасчетныйОборотыДтКт в периодах использовать другие параметры для\ задания периода например
&НачалоПериодаДействи и &КонецПериодаДействия - то эти параметры будут игнорироваться системой и вместо них будет использоваться парfметры &НачалоПериода и &КонецПериода.
Я конечно понимаю что система сама создает для виртуальной таблицы хоз.расчетного регистра эти параметры (т.е. явно их можно не указывать) , но что бы так игнорировать указанные - для меня это было открытие
Правильнее не "использовать всегда", а оформить кастомные параметры периодов виртуальных таблиц именно как параметры СКД - фигурными скобками. Тогда СКД не будет при автозаполнении фантазировать дефолтными параметрами СКД периодов виртуальных таблиц.
А вот еще у пустой ссылки в запросе реквизиты is null, а в объектной модели если реквизит ссылка то будет пустая ссылка, если число - то 0 и т.д., А еще для отладки формы в конфигураторе нужно Ctr + R нажать. А еще ...)
Проверяю тесты:
Первый:
Вернет пустую таблицу:
Первый:
ВЫБРАТЬ
1 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_Первая
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
10,
20,
NULL
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
3 КАК Поле1,
2 КАК ПолеБезNULL,
NULL КАК ПолеNULL
ПОМЕСТИТЬ ВТ_ВТОРАЯ
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
11,
22,
NULL
;
//////////////////////////////////////////////////////////// ////////////////////
ВЫБРАТЬ
ВТ_Первая.Поле1 КАК Поле1,
ВТ_Вторая.Поле1 КАК Поле11
ИЗ
ВТ_Первая КАК ВТ_Первая
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ВТОРАЯ КАК ВТ_Вторая
ПО (ВТ_Первая.ПолеNULL = ВТ_Вторая.ПолеNULL)
И (ВТ_Первая.ПолеNULL ЕСТЬ NULL)
И (ВТ_Вторая.ПолеNULL ЕСТЬ NULL)
ПоказатьВернет пустую таблицу:
Прикрепленные файлы:
Ликбез (копипаста)
NULL - это специальное значение, которое используется в SQL для обозначения отсутствия данных. Оно отличается от пустой строки или нулевого значения, так как NULL означает отсутствие какого-либо значения в ячейке таблицы.
История появления NULL в SQL довольно интересна и длинна. В начале 1970-х годов Д. Камерер (D. Chamberlin) и Р. Бойд (R. Boyce) предложили использовать реляционную модель для полной замены иерархических и сетевых моделей данных, которые были актуальны в то время. Полная замена предполагала возможность хранения значений NULL в таблицах структуры базы данных.
Первоначально, NULL был создан как интегральный элемент реляционной модели данных. Это означало, что NULL мог быть использован в качестве значения для любого типа данных (целого числа, строки и т.д.) или даже целой строки (например, таких значений как "неизвестно" или "нет данных").
Когда была разработана SQL, NULL был реализован как специальное значение или маркер, который указывает на отсутствие значения в столбце. Таким образом, в SQL NULL означает отсутствие значения или неопределенное значение.
Однако, NULL создал некоторые проблемы при работе с данными в SQL. Например, если вы выполняете операцию на столбце, содержащем NULL значение, результат операции также будет NULL. Это означает, что использование NULL может приводить к нежелательным результатам, таким как непредсказуемое поведение.
Однако, важно понимать, что NULL не обязательно означает отсутствие информации или отсутствие значения в столбце. NULL может быть использован для разных целей, таких как указание на неопределенный результат для вычислений или как маркер для отметки отсутствия значения в таблице.
NULL - это специальное значение, которое используется в SQL для обозначения отсутствия данных. Оно отличается от пустой строки или нулевого значения, так как NULL означает отсутствие какого-либо значения в ячейке таблицы.
История появления NULL в SQL довольно интересна и длинна. В начале 1970-х годов Д. Камерер (D. Chamberlin) и Р. Бойд (R. Boyce) предложили использовать реляционную модель для полной замены иерархических и сетевых моделей данных, которые были актуальны в то время. Полная замена предполагала возможность хранения значений NULL в таблицах структуры базы данных.
Первоначально, NULL был создан как интегральный элемент реляционной модели данных. Это означало, что NULL мог быть использован в качестве значения для любого типа данных (целого числа, строки и т.д.) или даже целой строки (например, таких значений как "неизвестно" или "нет данных").
Когда была разработана SQL, NULL был реализован как специальное значение или маркер, который указывает на отсутствие значения в столбце. Таким образом, в SQL NULL означает отсутствие значения или неопределенное значение.
Однако, NULL создал некоторые проблемы при работе с данными в SQL. Например, если вы выполняете операцию на столбце, содержащем NULL значение, результат операции также будет NULL. Это означает, что использование NULL может приводить к нежелательным результатам, таким как непредсказуемое поведение.
Однако, важно понимать, что NULL не обязательно означает отсутствие информации или отсутствие значения в столбце. NULL может быть использован для разных целей, таких как указание на неопределенный результат для вычислений или как маркер для отметки отсутствия значения в таблице.