Есть не null или не есть null: : Методическая поддержка для разработчиков и администраторов 1С:Предприятия 8
ЕСТЬNULL в запросе 1С 8.3
NULL – это не что иное, как отсутствие значения. Многие путают его со значением «0» типа число, пустой ссылкой на какой-либо объект или же с пустой строкой. Из-за этого заблуждения возникает много ошибок.
Значение NULL будет появляться в том случае, если в запросе будет обращение к несуществующему полю, свойству или к битой ссылке.
Язык запросов в 1С основан на SQL, который не позволяет проверять на значение NULL обычным равенством. Ниже описаны два способа проверки на NULL в 1С 8.3.
Функция ЕСТЬNULL()
Функция языка запросов 1С 8.3 ЕСТЬNULL() имеет два входных параметра:
- проверяемое выражение;
- выражение замены.
Наша команда предоставляет услуги по консультированию, настройке и внедрению 1С.
Связаться с нами можно по телефону +7 499 350 29 00.
Услуги и цены можно увидеть по ссылке.
Будем рады помочь Вам!
Если проверяемое значение будет NULL, то эта функция вернет значение выражения замены. Если же значение будет отлично от NULL, то вернется само проверяемое выражение.
Ниже рассмотрен пример. В нем выбираются все номенклатурные позиции табличной части товара из документа «Поступление товаров и услуг». При помощи левого соединения каждой номенклатуре проставляется последняя цена из регистра сведений «Цены номенклатуры».
В данном случае может возникнуть такая ситуация, что для какой-либо позиции может просто не быть цены в регистре. В таком случае функция ЕСТЬNULL вернет нам привычный ноль. Если ей не воспользоваться, то при попытке произвести арифметические операции над полем «Цена» со значением NULL мы получим ошибку.
ВЫБРАТЬ
Товары.Номенклатура КАК Товар,
ЕСТЬNULL(Цены.Цена, 0) КАК АктуальнаяЦена
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
ПО Товары.Номенклатура = Цены.Номенклатура
ГДЕ
Товары.Ссылка = &СсылкаНаДокумент
ЕСТЬ NULL в операторе ВЫБОР
Аналогом функции ЕСТЬNULL() является «ЕСТЬ NULL», которая используется в операторе ВЫБОР и проверяет, является ли значение NULL. «ЕСТЬ» в данном случае подразумевает равенство и запрос предыдущего примера будет выглядеть следующим образом:
ВЫБРАТЬ
Товары.Номенклатура КАК Товар,
ВЫБОР
КОГДА Цены.Цена ЕСТЬ NULL
ТОГДА 0
ИНАЧЕ Цены.Цена
КОНЕЦ КАК АктуальнаяЦена
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
ПО Товары.Номенклатура = Цены.Номенклатура
ГДЕ
Товары.Ссылка = &СсылкаНаДокумент
Отличия функции ЕСТЬNULL() от ЕСТЬ NULL
Как вы могли увидеть из предыдущих примеров, в обоих случаях запрос возвращает одни и те же данные. Функция ЕСТЬNULL() является сокращенным вариантом ВЫБОР КОГДА … ЕСТЬ NULL … КОНЕЦ, но она все же будет предпочтительнее по следующим причинам:
- Функция EСТЬNULL() оптимизирует запрос. Она считывается один раз, поэтому при проверке сложного выражения, запрос отработает быстрее.
- Функция EСТЬNULL() сокращает конструкцию, за счет чего запрос становится более читабельным.
- При выполнении функции EСТЬNULL() выражение замены приводится к типу проверяемого выражения для типов строковых типов (к длине строки) и числовых (к разрядности).
В чем разница между «is Not Null» и «Not Is Null»
нет никакой разницы.
мне кажется, что там может быть разница, когда дело доходит до производительности. Кто-нибудь хочет поподробнее?
все основные двигатели (то есть MySQL
, SQL Server
, Oracle
и PostgreSQL
) объединит эти предикаты на этапе разбора, составляя из них одинаковые планы.
обработка этих условий более сложна, чем простое применение операторов в том или ином порядке.
для например, в Oracle
, an IS NOT NULL
(или NOT IS NULL
) условие подразумевает возможность использования индекса, поэтому такой запрос:
SELECT column
FROM mytable
WHERE column IS NOT NULL
скорее всего, будет исполнен с index fast full scan
, без дополнительных проверок, сделанных во время выполнения (начиная с NULL
значения просто не попадут в индекс, поэтому нет смысла их проверять).
, даже если каждая запись должна быть проверена, порядок проверок определяется оптимизатором (и не по заказу предикатов и операторы появляются в WHERE
предложения).
например, вот план Oracle
запрос:
SQL> EXPLAIN PLAN FOR
2
2 SELECT *
3 FROM t_test
4 WHERE NOT column IS NULL
5 /
Explained
SQL> SELECT *
2 FROM TABLE(DBMS_XPLAN.display())
3 /
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 958699830
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 30 | 1260 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T_TEST | 30 | 1260 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COLUMN" IS NOT NULL)
Как видите,filter
был переведен внутренне в IS NOT NULL
(где Oracle
наряду с большинством комментаторов, кажется, считают более подходящей формой)
обновление:
как отметил Джонатан Леффлер, это разница при оценке кортежей (в отличие от одиночных столбцы.)
кортеж, состоящий из смешанных NULL
и неNULL
значения не являются ни NULL
или NOT NULL
.
на PostgreSQL
(который поддерживает этот предикат против кортежей), оба эти выражения:
SELECT (1, NULL) IS NULL
SELECT (1, NULL) IS NOT NULL
значение равно false.
В чем разница между «Is Not Null» и «не есть Null» — sql
Здесь нет никакой разницы.
Мне кажется, что есть разница, когда речь заходит о производительности. Кто-нибудь хочет поподробнее рассказать об этом?
Все основные движки (то есть MySQL
, SQL Server
, Oracle
и PostgreSQL
) будут объединять эти предикаты на стадии синтаксического анализа, составляя из них идентичные планы.
Обработка этих условий более сложна, чем простое применение операторов в том или ином порядке.
Например , в Oracle
условие IS NOT NULL
(или NOT IS NULL
) подразумевает возможность использования индекса, поэтому запрос, подобный этому:
SELECT column
FROM mytable
WHERE column IS NOT NULL
скорее всего, он будет выполняться с параметром index fast full scan
, без каких-либо дополнительных проверок во время выполнения (поскольку значения NULL
просто не попадут в индекс, поэтому проверять их нет смысла).
Даже если каждая запись будет нуждаться в проверке, порядок проверок будет определен оптимизатором (а не порядком появления предикатов и операторов в предложении WHERE
).
Например, вот план для запроса Oracle
:
SQL> EXPLAIN PLAN FOR
2
2 SELECT *
3 FROM t_test
4 WHERE NOT column IS NULL
5 /
Explained
SQL> SELECT *
2 FROM TABLE(DBMS_XPLAN.display())
3 /
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 958699830
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 30 | 1260 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T_TEST | 30 | 1260 | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COLUMN" IS NOT NULL)
Как вы можете видеть, filter
был переведен внутренне в IS NOT NULL
(который Oracle
вместе с большинством комментаторов, похоже, считает более подходящей формой)
Обновление:
Как отметил Джонатан Леффлер, это различие при оценке кортежей (в отличие от одиночных столбцов).
Кортеж, состоящий из смешанных значений NULL
и не-NULL
, не является ни NULL
, ни NOT NULL
.
В PostgreSQL
(который поддерживает этот предикат против кортежей) оба эти выражения:
SELECT (1, NULL) IS NULL
SELECT (1, NULL) IS NOT NULL
оценить значение false.
загадочное дело выражения null >= 0 / Блог компании RUVDS.com / Хабр
Однажды я собирал материалы чтобы устроить ликбез по JavaScript для пары коллег. Тогда я и наткнулся на довольно интересный пример, в котором рассматривалось сравнение значения null
с нулём. Собственно говоря, вот этот пример:
null > 0; // false
null == 0; // false
null >= 0; // true
На первый взгляд — полная бессмыслица. Как некое значение может быть не больше, чем 0, не равно нулю, но при этом быть больше или равно нулю?
Хотя поначалу я оставил это без особого внимания, решив, что всё дело в том, что JavaScript — это JavaScript, со всеми его странностями, этот пример меня заинтриговал. Связано ли это с типом null
и с тем, как он обрабатывается, или с тем, как выполняются операции сравнения значений?
В итоге я решил докопаться до сути происходящего и начал рыться в единственном источнике истины для JavaScript — в спецификации ECMA. Сегодня я хочу рассказать вам о том, в какую глубокую кроличью нору я в результате провалился.
Абстрактный алгоритм сравнения для отношений
Рассмотрим первое сравнение:
null > 0; // false
В соответствии со спецификацией, операторы сравнения >
и <
, для того, чтобы выяснить, истинно или ложно выражение, пропускают его через так называемый абстрактный алгоритм сравнения для отношений. Здесь и далее мы будем цитировать фрагменты спецификации по тексту перевода «Стандарт ECMA-262, 3я редакция» с ресурса javascript.ru:
Сравнение x < y, где x и y являются значениями, возвращает true, false или undefined (последнее означает, что хотя бы один из операндов равен NaN). Такое сравнение производится следующим образом:
1. Вызвать ToPrimitive(x, подсказка Number).
2. Вызвать ToPrimitive(y, подсказка Number).
3. Если Тип(Результата(1)) равен String и Тип(Результата(2)) равен String - переход на шаг 16. (Заметим, что этот шаг отличается от шага 7 в алгоритме для оператора сложения + тем, что в нём используется и вместо или.)
4. Вызвать ToNumber(Результат(1)).
5. Вызвать ToNumber(Результат(2)).
6. Если Результат(4) равен NaN - вернуть undefined.
7. Если Результат(5) равен NaN - вернуть undefined.
8. Если Результат(4) и Результат(5) являются одинаковыми числовыми значениями - вернуть false.
9. Если Результат(4) равен +0 и Результат(5) равен -0 - вернуть false.
10. Если Результат(4) равен -0 и Результат(5) равен +0 - вернуть false.
11. Если Результат(4) равен +∞, вернуть false.
12. Если Результат(5) равен +∞, вернуть true.
13. Если Результат(5) равен -∞, вернуть false.
14. Если Результат(4) равен -∞, вернуть true.
15. Если математическое значение Результата (4) меньше, чем математическое значение Результата(5) (заметим, что эти математические значения оба конечны и не равны нулю) - вернуть true. Иначе вернуть false.
16. Если Результат(2) является префиксом Результата(1), вернуть false. (Строковое значение p является префиксом строкового значения q, если q может быть результатом конкатенации p и некоторой другой строки r. Отметим, что каждая строка является своим префиксом, т.к. r может быть пустой строкой.)
17. Если Результат(1) является префиксом Результата(2), вернуть true.
18. Пусть k - наименьшее неотрицательное число такое, что символ на позиции k Результата(1) отличается от символа на позиции k Результата(2). (Такое k должно существовать, т.к. на данном шаге установлено, что ни одна из строк не является префиксом другой.)
19. Пусть m - целое, равное юникодному коду символа на позиции k строки Результат(1).
20. Пусть n - целое, равное юникодному коду символа на позиции k строки Результат(2).
21. Если m < n, вернуть true. Иначе вернуть false.
Пройдёмся по этому алгоритму с нашим выражением null > 0
.
Шаги 1 и 2 предлагают нам вызвать оператор ToPrimitive()
для значений null
и 0
для того, чтобы привести эти значения к их элементарному типу (к такому, например, как Number
или String
). Вот как ToPrimitive преобразует различные значения:
Входной тип | Результат |
Undefined | Преобразование не производится |
Null | Преобразование не производится |
Boolean | Преобразование не производится |
Number | Преобразование не производится |
String | Преобразование не производится |
Object | Возвращает значение по умолчанию для объекта. Значение по умолчанию для объекта получается путём вызова для объекта внутреннего метода [[DefaultValue]] с передачей ему опциональной подсказки ПредпочтительныйТип. |
В соответствии с таблицей, ни к левой части выражения, null
, ни к правой части, 0
, никаких преобразований не применяется.
Шаг 3 алгоритма в нашем случае неприменим, пропускаем его и идём дальше. На шагах 4 и 5 нам нужно преобразовать левую и правую части выражения к типу Number
. Преобразование к типу Number выполняется в соответствии со следующей таблицей (здесь опущены правила преобразования для входных типов String
и Object
, так как они к теме нашего разговора отношения не имеют):
Входной тип | Результат |
Undefined | NaN |
Null | +0 |
Boolean | Результат равен 1, если аргумент равен true. Результат равен +0, если аргумент равен false. |
Number | Преобразование не производится |
… | … |
В соответствии с таблицей, null
будет преобразовано в +0
, а 0
останется самим собой. Ни одно из этих значений не является NaN
, поэтому шаги алгоритма 6 и 7 можно пропустить. А вот на шаге 8 нам надо остановиться. Значение +0
равно 0
, в результате алгоритм возвращает false
. Таким образом:
null > 0; // false
null < 0; // тоже false
Итак, почему null
не больше и не меньше нуля мы выяснили. Теперь идём дальше — разберёмся с тем, почему null
ещё и не равен нулю.
Абстрактный алгоритм сравнения для равенств
Рассмотрим теперь проверку на равенство null
и 0
:
null == 0; //false
Оператор ==
использует так называемый абстрактный алгоритм сравнения для равенств, возвращая в результате true
или false
. Вот этот алгоритм:
Сравнение x == y, где x и y являются значениями, возвращает true или false. Такое сравнение производится следующим образом:
1. Если Тип(x) отличается от Типа(y) - переход на шаг 14.
2. Если Тип(x) равен Undefined - вернуть true.
3. Если Тип(x) равен Null - вернуть true.
4. Если Тип(x) не равен Number - переход на шаг 11.
5. Если x является NaN - вернуть false.
6. Если y является NaN - вернуть false.
7. Если x является таким же числовым значением, что и y, - вернуть true.
8. Если x равен +0, а y равен -0, вернуть true.
9. Если x равен -0, а y равен +0, вернуть true.
10. Вернуть false.
11. Если Тип(x) равен String - вернуть true, если x и y являются в точности одинаковыми последовательностями символов (имеют одинаковую длину и одинаковые символы в соответствующих позициях). Иначе вернуть false.
12. Если Тип(x) равен Boolean, вернуть true, если x и y оба равны true или оба равны false. Иначе вернуть false.
13. Вернуть true, если x и y ссылаются на один и тот же объект или они ссылаются на объекты, которые были объединены вместе (см. раздел 13.1.2). Иначе вернуть false.
14. Если x равно null, а y равно undefined - вернуть true.
15. Если x равно undefined, а y равно null - вернуть true.
16. Если Тип(x) равен Number, а Тип(y) равен String, вернуть результат сравнения x == ToNumber(y).
17. Если Тип(x) равен String, а Тип(y) равен Number, вернуть результат сравнения ToNumber(x)== y.
18. Если Тип(x) равен Boolean, вернуть результат сравнения ToNumber(x)== y.
19. Если Тип(y) равен Boolean, вернуть результат сравнения x == ToNumber(y).
20. Если Тип(x) - String или Number, а Тип(y) - Object, вернуть результат сравнения x == ToPrimitive(y).
21. Если Тип(x) - Object, а Тип(y) - String или Number, вернуть результат сравнения ToPrimitive(x)== y.
22. Вернуть false.
Пытаясь понять, равно ли значение null
значению 0, мы сразу переходим из шага 1 к шагу 14, так как Тип(x) отличается от Типа(y)
. Как ни странно, но шаги 14-21 тоже к нашему случаю не подходят, так как Тип(х) —
это null
. Наконец мы попадаем на шаг 22, после чего false
возвращается как значение по умолчанию!
В результате и оказывается, что:
null == 0; //false
Теперь, когда ещё одна «тайна» JavaScript» раскрыта, разберёмся с оператором «больше или равно».
Оператор больше или равно (>=)
Выясним теперь, почему истинно такое выражение:
null >= 0; // true
Тут спецификация полностью выбила меня из колеи. Вот как, на очень высоком уровне, работает оператор >=:
Если null < 0 принимает значение false, то null >= 0 принимает значение true
В результате мы и получаем:
null >= 0; // true
И, на самом деле, в этом есть смысл. С точки зрения математики, если у нас есть два числа, x
и y
, и если x
не меньше, чем y
, тогда x
должно быть больше чем y
или равно ему.
Я предполагаю, что данный оператор работает именно так для того, чтобы оптимизировать вычисления. Зачем сначала проверять, больше ли x
чем y
, и, если это не так, проверять, равняется ли значение x
значению y
, если можно выполнить всего одно сравнение, проверить, меньше ли x
чем y
, а затем использовать результат этого сравнения для того, чтобы вывести результат исходного выражения.
Итоги
Вопрос о сравнении null
и 0
, на самом деле, не такой уж и сложный. Однако, поиск ответа открыл мне кое-что новое о JavaScript. Надеюсь, мой рассказ сделал то же самое для вас.
Уважаемые читатели! Знаете ли вы о каких-нибудь странностях JavaScript, которые, после чтения документации, уже перестают казаться таковыми?
0 или NULL? / Хабр
Есть три агрегатные функции, которые чаще всего используются на практике: COUNT, SUM и AVG.
И если первая уже обсуждалась ранее, то с остальными есть интересные нюансы с производительностью. Но давайте обо всем по порядку…
При использовании агрегатных функций на плане выполнения, в зависимости от входного потока, может встречаться два оператора: Stream Aggregate и Hash Match.
Для выполнения первого может требоваться предварительно отсортированный входной набор значений и при этом Stream Aggregate не блокирует выполнение последующих за ним операторов.
В свою очередь, Hash Match является блокирующим оператором (за редким исключением) и не требует сортировки входного потока. Для работы Hash Match используется хеш-таблица, которая создается в памяти и в случае неправильной оценки ожидаемого количества строк, оператор может сливать результаты в tempdb.
Итого получается, что Stream Aggregate хорошо работает на небольших отсортированных наборах данных, а Hash Match хорошо справляется с большими не отсортированными наборами и хорошо поддается параллельной обработке.
Теперь, когда мы преодолели теорию начнем смотреть как работают агрегатные функции.
Предположим, что нам нужно подсчитать среднюю цену среди всех продуктов:
SELECT AVG(Price) FROM dbo.Price
По таблице с достаточно простой структурой:
CREATE TABLE dbo.Price (
ProductID INT PRIMARY KEY,
LastUpdate DATE NOT NULL,
Price SMALLMONEY NULL,
Qty INT
)
Поскольку у нас происходит скалярная агрегация, на плане выполнения мы ожидаемо увидим Stream Aggregate:
Внутри этот оператор выполняет две агрегирующие операции COUNT_BIG и SUM (хотя на физическом уровне выполняется это как одна операция) по столбцу Price:
Не забываем, что среднее вычисляется только для NOT NULL, поскольку операция COUNT_BIG идет по столбцу, а не со звездочкой. Соответственно, такой запрос:
SELECT AVG(v)
FROM (
VALUES (3), (9), (NULL)
) t(v)
вернет в качестве результата не 4, а 6.
Теперь посмотрим на Compute Scalar, внутри которого есть интересное выражение для проверки деления на ноль:
Expr1003 =
CASE WHEN [Expr1004]=(0)
THEN NULL
ELSE [Expr1005]/CONVERT_IMPLICIT(money,[Expr1004],0)
END
Попробуем подсчитать общую сумму:
SELECT SUM(Price) FROM dbo.Price
План выполнения останется прежним:
Но если посмотреть на операции, которые выполняет Stream Aggregate…
можно капельку удивиться. Зачем SQL Server подсчитывает количество, если мне нужна только сумма? Ответ кроется в Compute Scalar:
[Expr1003] = Scalar Operator(CASE WHEN [Expr1004]=(0) THEN NULL ELSE [Expr1005] END)
Если не брать во внимание COUNT, то согласно семантике языка T-SQL, когда нет строк во входном потоке, то мы должны возвращать NULL, а не 0. Такое поведение работает как для скалярной, так и для векторной агрегации:
SELECT LastUpdate, SUM(Price)
FROM dbo.Price
GROUP BY LastUpdate
OPTION(MAXDOP 1)
Expr1003 = Scalar Operator(CASE WHEN [Expr1008]=(0) THEN NULL ELSE [Expr1009] END)
Более того, такая проверка делается как для NULL, так и для NOT NULL столбцов. Теперь рассмотрим примеры в которых будут полезны описанные выше особенности SUM и AVG.
Если мы хотим посчитать среднее, то не нужно использовать COUNT + SUM:
SELECT SUM(Price) / COUNT(Price) FROM dbo.Price
Поскольку такой запрос будет менее эффективным, чем явное использование AVG.
Далее… Явно передавать NULL в агрегатную функцию нет необходимости:
SELECT
SUM(CASE WHEN Price < 100 THEN Qty ELSE NULL END),
SUM(CASE WHEN Price > 100 THEN Qty ELSE NULL END)
FROM dbo.Price
Поскольку в такой конструкции:
SELECT
SUM(CASE WHEN Price < 100 THEN Qty END),
SUM(CASE WHEN Price > 100 THEN Qty END)
FROM dbo.Price
Оптимизатор подстановку делает автоматически:
Но что, если я хочу получить 0 в результатах вместо NULL? Очень часто используют ELSE и не задумываются:
SELECT
SUM(CASE WHEN Price < 100 THEN Qty ELSE 0 END),
SUM(CASE WHEN Price > 100 THEN Qty ELSE 0 END)
FROM dbo.Price
Очевидно, что в таком случае мы достигнем желаемого… да и одно предупреждение перестанет мозолить глаза:
Warning: Null value is eliminated by an aggregate or other SET operation.
Хотя лучше всего писать запрос вот так:
SELECT
ISNULL(SUM(CASE WHEN Price < 100 THEN Qty END), 0),
ISNULL(SUM(CASE WHEN Price > 100 THEN Qty END), 0)
FROM dbo.Price
И это хорошо не потому, что оператор CASE станет работать быстрее. Мы то уже знаем, что оптимизатор туда подставляет ELSE NULL автоматом… Так в чем же преимущества последнего варианта?
Как оказалось, операции агрегирования, в которых преобладают NULL значения обрабатываются быстрее.
SET STATISTICS TIME ON
DECLARE @i INT = NULL
;WITH
E1(N) AS (
SELECT * FROM (
VALUES
(@i),(@i),(@i),(@i),(@i),
(@i),(@i),(@i),(@i),(@i)
) t(N)
),
E2(N) AS (SELECT @i FROM E1 a, E1 b),
E4(N) AS (SELECT @i FROM E2 a, E2 b),
E8(N) AS (SELECT @i FROM E4 a, E4 b)
SELECT SUM(N) -- 100.000.000
FROM E8
OPTION (MAXDOP 1)
Выполнение у меня заняло:
SQL Server Execution Times:
CPU time = 5985 ms, elapsed time = 5989 ms.
Теперь меняем:
DECLARE @i INT = 0
И выполняем повторно:
SQL Server Execution Times:
CPU time = 6437 ms, elapsed time = 6451 ms.
Не так существенно, но повод для оптимизации тем не менее это дает в определенных ситуациях.
Конец спектакля и занавес? Нет. Это еще не все…
Как говорил один мой знакомый: «Нет ни черного, ни белого… Мир многоцветен» и поэтому напоследок приведу интересный пример, когда NULL может вредить.
Создадим медленную функцию и тестовую таблицу:
USE tempdb
GO
IF OBJECT_ID('dbo.udf') IS NOT NULL
DROP FUNCTION dbo.udf
GO
CREATE FUNCTION dbo.udf (@a INT)
RETURNS VARCHAR(MAX)
AS BEGIN
DECLARE @i INT = 1000
WHILE @i > 0 SET @i -= 1
RETURN REPLICATE('A', @a)
END
GO
IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp
GO
;WITH
E1(N) AS (
SELECT * FROM (
VALUES
(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1)
) t(N)
),
E2(N) AS (SELECT 1 FROM E1 a, E1 b),
E4(N) AS (SELECT 1 FROM E2 a, E2 b)
SELECT *
INTO #temp
FROM E4
И выполним запрос:
SET STATISTICS TIME ON
SELECT SUM(LEN(dbo.udf(N)))
FROM #temp
SQL Server Execution Times:
CPU time = 9109 ms, elapsed time = 11603 ms.
Теперь попробуем результат выражения, который передается в SUM, обернуть в ISNULL:
SELECT SUM(ISNULL(LEN(dbo.udf(N)), 0))
FROM #temp
SQL Server Execution Times:
CPU time = 4562 ms, elapsed time = 5719 ms.
Скорость выполнения сократилась в 2 раза. Сразу скажу, что это не магия… А баг в движке SQL Server-а, который Microsoft уже «вроде как» исправила в SQL Server 2012 CTP.
Суть проблемы в следующем: результат выражения внутри функций SUM или AVG может выполняться дважды, если оптимизатор считает, что может вернуться NULL.
Все тестировалось на Microsoft SQL Server 2012 (SP3) (KB3072779) — 11.0.6020.0 (X64).
Если хотите поделиться этой статьей с англоязычной аудиторией:
What is faster inside SUM & AVG: 0 or NULL?
SQL: IS NOT NULL Условие
В этом руководстве по SQL объясняется, как использовать условие SQL IS NOT NULL с синтаксисом и примерами.
Описание
Условие IS NOT NULL используется в SQL для проверки ненулевого значения. Он возвращает TRUE, если найдено значение, отличное от NULL, в противном случае возвращает FALSE. Его можно использовать в операторах SELECT, INSERT, UPDATE или DELETE.
Синтаксис
Синтаксис условия IS NOT NULL в SQL:
выражение НЕ ПУСТО
Параметры или аргументы
- выражение
- Выражение, которое нужно проверить на наличие НЕ NULL значения.
DDL / DML для примеров
Если вы хотите следовать этому руководству, получите DDL для создания таблиц и DML для заполнения данных. Тогда попробуйте примеры в своей базе данных!
Получить DDL / DML
Пример — использование IS NOT NULL с оператором SELECT
При проверке значения, отличного от NULL, рекомендуется использовать оператор сравнения IS NOT NULL в SQL. Начнем с рассмотрения примера, показывающего, как использовать условие IS NOT NULL в операторе SELECT.
В этом примере у нас есть таблица с именем продуктов со следующими данными:
product_id | название_продукта | category_id |
---|---|---|
1 | Груша | 50 |
2 | Банан | 50 |
3 | оранжевый | 50 |
4 | Яблоко | 50 |
5 | Хлеб | 75 |
6 | Ветчина нарезанная | 25 |
7 | Клинекс | NULL |
Введите следующий оператор SQL:
Попробуй это
ВЫБРАТЬ * ИЗ продуктов ГДЕ category_id НЕ ПУСТО;
Будет выбрано 6 записей.Вот результаты, которые вы должны увидеть:
product_id | название_продукта | category_id |
---|---|---|
1 | Груша | 50 |
2 | Банан | 50 |
3 | оранжевый | 50 |
4 | Яблоко | 50 |
5 | Хлеб | 75 |
6 | Ветчина нарезанная | 25 |
В этом примере будут возвращены все записи из таблицы products , где customer_id не содержит значения NULL.
Пример — использование IS NOT NULL с оператором UPDATE
Далее давайте рассмотрим пример использования условия IS NOT NULL в операторе UPDATE.
В этом примере у нас есть таблица с именем клиентов со следующими данными:
customer_id | фамилия | first_name | избранное_вебсайт |
---|---|---|---|
4000 | Джексон | Джо | techonthenet.com |
5000 | Смит | Джейн | digminecraft.com |
6000 | Фергюсон | Саманта | bigactivities.com |
7000 | Рейнольдс | Аллен | checkyourmath.com |
8000 | Андерсон | Пейдж | NULL |
9000 | Джонсон | Дерек | techonthenet.com |
Введите следующий оператор UPDATE:
Попробуй это
ОБНОВЛЕНИЕ клиентов УСТАНОВИТЬ избранное_website = 'techonthenet.com' ГДЕ favourite_website НЕ ПУСТО;
Будет обновлено 5 записей. Снова выберите данные из таблицы клиентов :
ВЫБРАТЬ * ИЗ клиентов;
Вот результаты, которые вы должны увидеть:
customer_id | фамилия | first_name | избранное_вебсайт |
---|---|---|---|
4000 | Джексон | Джо | techonthenet.com |
5000 | Смит | Джейн | techonthenet.com |
6000 | Фергюсон | Саманта | techonthenet.com |
7000 | Рейнольдс | Аллен | techonthenet.com |
8000 | Андерсон | Пейдж | NULL |
9000 | Джонсон | Дерек | techonthenet.com |
В этом примере все значения favourite_website в таблице customers будут обновлены до «techonthenet.com», где favourite_website содержит значение NULL. Как видите, favourite_website обновлен всего в одной строке.
Пример — использование IS NOT NULL с оператором DELETE
Далее давайте рассмотрим пример использования условия IS NULL в операторе DELETE.
В этом примере у нас есть таблица с именем заказов со следующими данными:
order_id | customer_id | дата заказа |
---|---|---|
1 | 7000 | 18.04.2016 |
2 | 5000 | 18.04.2016 |
3 | 8000 | 04.04.19 |
4 | 4000 | 20.04.2016 |
5 | NULL | 01.05.2016 |
Введите следующую инструкцию DELETE:
Попробуй это
УДАЛИТЬ ИЗ заказов ГДЕ customer_id НЕ ПУСТО;
Будет удалено 4 записи.Снова выберите данные из таблицы заказов :
ВЫБРАТЬ * ИЗ заказов;
Вот результаты, которые вы должны увидеть:
order_id | customer_id | дата заказа |
---|---|---|
5 | NULL | 01.05.2016 |
В этом примере будут удалены все записи из таблицы orders , где customer_id не содержит значения NULL.
.
mysql — Разница между «IS NOT NULL» и «NOT (field = NULL)» в этих 2 запросах
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.
значений SQL NULL — ЕСТЬ NULL и НЕ NULL
Что такое значение NULL?
Поле со значением NULL — это поле без значения.
Если поле в таблице является необязательным, можно вставить новую запись или
обновить запись без добавления значения в это поле. Тогда поле будет
сохраняется со значением NULL.
Примечание: ПУСТОЕ значение отличается от нулевого значения или поля, которое
содержит пробелы. Поле со значением NULL — это поле, оставленное пустым.
при создании записи!
Как проверить значения NULL?
Невозможно проверить значения NULL с помощью операторов сравнения, таких как
=, <или <>.
Вместо этого нам придется использовать операторы IS NULL и IS NOT NULL.
IS NULL Синтаксис
ВЫБЕРИТЕ имена_столбцов
ИЗ имя_таблицы
ГДЕ имя_столбца ЕСТЬ NULL;
IS NOT NULL Синтаксис
ВЫБЕРИТЕ имена_столбцов
ИЗ имя_таблицы
ГДЕ имя_столбца НЕ ПУСТО;
Демо-база данных
Ниже представлен выбор из таблицы «Клиенты» в примере Northwind.
база данных:
Идентификатор клиента | Имя клиента | ContactName | Адрес | Город | Почтовый индекс | Страна |
---|---|---|---|---|---|---|
1 | Альфредс Футтеркисте | Мария Андерс | Obere Str.57 | Берлин | 12209 | Германия |
2 | Ana Trujillo Emparedados y helados | Ана Трухильо | Avda. de la Constitución 2222 | México D.F. | 05021 | Мексика |
3 | Антонио Морено Такерия | Антонио Морено | Матадерос 2312 | Мексика Д.F. | 05023 | Мексика |
4 | Вокруг Рога | Томас Харди | 120 Ганновер пл. | Лондон | WA1 1DP | Великобритания |
5 | Berglunds snabbköp | Кристина Берглунд | Berguvsvägen 8 | Лулео | С-958 22 | Швеция |
Оператор IS NULL
Оператор IS NULL используется для проверки пустых значений (значений NULL).
В следующем SQL-запросе перечислены все клиенты со значением NULL в поле «Адрес»:
Пример
ВЫБЕРИТЕ CustomerName, ContactName, Address
FROM Customers
WHERE Address
НУЛЕВОЙ;
Попробуй сам »
Совет: Всегда используйте IS NULL для поиска значений NULL.
Оператор IS NOT NULL
Оператор IS NOT NULL используется для проверки непустых значений (NOT NULL
ценности).
Следующий SQL перечисляет всех клиентов со значением в поле «Адрес»:
Пример
ВЫБЕРИТЕ CustomerName, ContactName, Address
FROM Customers
WHERE Address
НЕ НУЛЬ;
Попробуй сам »
.
java — JPQL IS NOT NULL возвращает объекты с NULL
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
Загрузка…
.