0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>На практике очень редко можно столкнуться с таблицами, содержащие абсолютно чистые и полные данные. Более вероятно, что вы будете работать с таблицами, в которых некоторые значения отсутствуют. В SQL эти отсутствующие данные обозначаются как NULL. Обработка таких значений - это важный навык для аналитика, потому что неправильное управление NULL-значениями может привести к искаженным результатам и ошибочным выводам.</p>
1
<p>На практике очень редко можно столкнуться с таблицами, содержащие абсолютно чистые и полные данные. Более вероятно, что вы будете работать с таблицами, в которых некоторые значения отсутствуют. В SQL эти отсутствующие данные обозначаются как NULL. Обработка таких значений - это важный навык для аналитика, потому что неправильное управление NULL-значениями может привести к искаженным результатам и ошибочным выводам.</p>
2
<p>Чтобы попрактиковаться в работе с NULL в SQL, мы использовали нашу<a>базу данных</a>и составили в ней таблицу delivery, которая содержит следующие столбцы:</p>
2
<p>Чтобы попрактиковаться в работе с NULL в SQL, мы использовали нашу<a>базу данных</a>и составили в ней таблицу delivery, которая содержит следующие столбцы:</p>
3
<ul><li>id доставки (delivery_id)</li>
3
<ul><li>id доставки (delivery_id)</li>
4
<li>id заказа (order_id)</li>
4
<li>id заказа (order_id)</li>
5
<li>дата доставки (delivery_date)</li>
5
<li>дата доставки (delivery_date)</li>
6
<li>адрес доставки (delivery_address)</li>
6
<li>адрес доставки (delivery_address)</li>
7
</ul><p>В этой таблице мы оставили пропуски в дате доставки и адресе доставки, чтобы показать, как SQL операторы могут обрабатывать эти NULL-значения.</p>
7
</ul><p>В этой таблице мы оставили пропуски в дате доставки и адресе доставки, чтобы показать, как SQL операторы могут обрабатывать эти NULL-значения.</p>
8
<h2>Операторы для обработки NULL в SQL</h2>
8
<h2>Операторы для обработки NULL в SQL</h2>
9
<p>Для начала познакомимся с оператором COALESCE. С его помощью можно выбрать первое ненулевое значение из списка. Он принимает два или более аргументов и возвращает первый аргумент, который не равен NULL. Если все аргументы равны NULL, COALESCE возвращает NULL.</p>
9
<p>Для начала познакомимся с оператором COALESCE. С его помощью можно выбрать первое ненулевое значение из списка. Он принимает два или более аргументов и возвращает первый аргумент, который не равен NULL. Если все аргументы равны NULL, COALESCE возвращает NULL.</p>
10
<p>Предположим, мы хотим получить адрес доставки для каждого заказа, но в некоторых случаях адрес доставки отсутствует. Для таких случаев мы можем использовать COALESCE, чтобы вместо NULL вывести строку с текстом "Адрес не указан". Вот как это можно сделать:</p>
10
<p>Предположим, мы хотим получить адрес доставки для каждого заказа, но в некоторых случаях адрес доставки отсутствует. Для таких случаев мы можем использовать COALESCE, чтобы вместо NULL вывести строку с текстом "Адрес не указан". Вот как это можно сделать:</p>
11
<p>В этом запросе для каждого заказа из таблицы delivery мы получаем два параметра - order_id и delivery_address. Если delivery_address равен NULL, оператор COALESCE заменяет его на строку 'Адрес не указан'.</p>
11
<p>В этом запросе для каждого заказа из таблицы delivery мы получаем два параметра - order_id и delivery_address. Если delivery_address равен NULL, оператор COALESCE заменяет его на строку 'Адрес не указан'.</p>
12
<p>Таким образом, даже если в исходных данных есть отсутствующие значения, мы все равно получаем полезную информацию для каждого заказа.</p>
12
<p>Таким образом, даже если в исходных данных есть отсутствующие значения, мы все равно получаем полезную информацию для каждого заказа.</p>
13
<p>Аналогично оператору COALESCE, мы можем использовать IFNULL - получится тот же результат. Оператор IFNULL принимает два аргумента и возвращает первый, если он не NULL. В противном случае возвращается второй аргумент.</p>
13
<p>Аналогично оператору COALESCE, мы можем использовать IFNULL - получится тот же результат. Оператор IFNULL принимает два аргумента и возвращает первый, если он не NULL. В противном случае возвращается второй аргумент.</p>
14
<p>Для приведенного примера с таблицей delivery запрос будет выглядеть так:</p>
14
<p>Для приведенного примера с таблицей delivery запрос будет выглядеть так:</p>
15
<p>Результат запроса будет совпадать с результатом использования COALESCE</p>
15
<p>Результат запроса будет совпадать с результатом использования COALESCE</p>
16
<p>В SQL также есть операторы NVL, NVL2 и DECODE. Они также позволяют обрабатывать NULL-значения, но не поддерживаются в СУБД SQlite. В этом смысле надежнее всего использовать оператор COALESCE, потому что он поддерживается практически во всех известных реляционных СУБД.</p>
16
<p>В SQL также есть операторы NVL, NVL2 и DECODE. Они также позволяют обрабатывать NULL-значения, но не поддерживаются в СУБД SQlite. В этом смысле надежнее всего использовать оператор COALESCE, потому что он поддерживается практически во всех известных реляционных СУБД.</p>
17
<h2>Риски работы с NULL</h2>
17
<h2>Риски работы с NULL</h2>
18
<p>Существует множество различных нюансов при работе с NULL значениями, которые всегда следует учитывать.</p>
18
<p>Существует множество различных нюансов при работе с NULL значениями, которые всегда следует учитывать.</p>
19
<p>Для примера попробуем найти всех клиентов, у которых не указан возраст. Если мы используем оператор =, запрос не вернет никаких результатов, даже если в таблице есть клиенты с возрастом NULL:</p>
19
<p>Для примера попробуем найти всех клиентов, у которых не указан возраст. Если мы используем оператор =, запрос не вернет никаких результатов, даже если в таблице есть клиенты с возрастом NULL:</p>
20
<p>SQL считает, что NULL не равно ничему, даже другому NULL. Поэтому age = NULL всегда возвращает false, и никакие строки не выбираются.</p>
20
<p>SQL считает, что NULL не равно ничему, даже другому NULL. Поэтому age = NULL всегда возвращает false, и никакие строки не выбираются.</p>
21
<p>Вместо этого следует использовать оператор IS NULL:</p>
21
<p>Вместо этого следует использовать оператор IS NULL:</p>
22
<p>Этот запрос вернет всех клиентов, у которых в столбце age указано значение NULL - то есть не указан возраст.</p>
22
<p>Этот запрос вернет всех клиентов, у которых в столбце age указано значение NULL - то есть не указан возраст.</p>
23
<p>Еще следует помнить, что арифметические операции с NULL в SQL всегда возвращают NULL. Например, мы берем таблицу customers и хотим увеличить customer_id каждого клиента на единицу:</p>
23
<p>Еще следует помнить, что арифметические операции с NULL в SQL всегда возвращают NULL. Например, мы берем таблицу customers и хотим увеличить customer_id каждого клиента на единицу:</p>
24
<p>Если значение customer_id было NULL, то updated_id также будет NULL, несмотря на прибавление единицы. Это может привести к неожиданным результатам, ведь мы ожидали увеличение на единицу во всех customer_id. Чтобы с такой проблемой не сталкиваться, можно использовать COALESCE и заменить NULL на 0 перед выполнением арифметической операции:</p>
24
<p>Если значение customer_id было NULL, то updated_id также будет NULL, несмотря на прибавление единицы. Это может привести к неожиданным результатам, ведь мы ожидали увеличение на единицу во всех customer_id. Чтобы с такой проблемой не сталкиваться, можно использовать COALESCE и заменить NULL на 0 перед выполнением арифметической операции:</p>
25
<p>Еще один неочевидный момент - мы можем случайно нарушить связи между таблицами, если попытаемся соединить данные из двух таблиц, во внешнем ключе которых есть NULL.</p>
25
<p>Еще один неочевидный момент - мы можем случайно нарушить связи между таблицами, если попытаемся соединить данные из двух таблиц, во внешнем ключе которых есть NULL.</p>
26
<p>Вернемся к нашей таблице orders. В ней столбец product_id является внешним ключом - то есть он ссылается на столбец product_id в другой таблице products. При этом у нас есть заказы с product_id = NULL.</p>
26
<p>Вернемся к нашей таблице orders. В ней столбец product_id является внешним ключом - то есть он ссылается на столбец product_id в другой таблице products. При этом у нас есть заказы с product_id = NULL.</p>
27
<p>Если мы попытаемся связать данные заказа с данными клиента, то заказы с product_id = NULL не свяжутся с продуктом:</p>
27
<p>Если мы попытаемся связать данные заказа с данными клиента, то заказы с product_id = NULL не свяжутся с продуктом:</p>
28
<p>В этом запросе заказы с product_id = NULL не включились в таблицу, потому что их нельзя связать с продуктами по внешнему ключу. Это может привести к потере информации в результатах запроса, если эти заказы важны для анализа.</p>
28
<p>В этом запросе заказы с product_id = NULL не включились в таблицу, потому что их нельзя связать с продуктами по внешнему ключу. Это может привести к потере информации в результатах запроса, если эти заказы важны для анализа.</p>
29
<p>Чтобы учесть такие заказы, можно использовать LEFT JOIN вместо INNER JOIN:</p>
29
<p>Чтобы учесть такие заказы, можно использовать LEFT JOIN вместо INNER JOIN:</p>
30
<p>Теперь все заказы будут включены в результат, но product_name будет равен NULL для заказов, у которых product_id = NULL.</p>
30
<p>Теперь все заказы будут включены в результат, но product_name будет равен NULL для заказов, у которых product_id = NULL.</p>
31
<p>Также при работе с NULL следует помнить о нюансах, с которыми мы столкнулись на предыдущих уроках.</p>
31
<p>Также при работе с NULL следует помнить о нюансах, с которыми мы столкнулись на предыдущих уроках.</p>
32
<p>Например, NULL-значения могут появляться в разных местах в результате сортировки в зависимости от СУБД. В некоторых они появляются на вершине при сортировке по возрастанию, а в других - на дне. С помощью операторов NULLS LAST и NULLS FIRST мы можем указать явно, где должны располагаться значения NULL в результирующем наборе данных.</p>
32
<p>Например, NULL-значения могут появляться в разных местах в результате сортировки в зависимости от СУБД. В некоторых они появляются на вершине при сортировке по возрастанию, а в других - на дне. С помощью операторов NULLS LAST и NULLS FIRST мы можем указать явно, где должны располагаться значения NULL в результирующем наборе данных.</p>
33
<p>Наконец, при работе с агрегирующими функциями (например, COUNT, AVG, SUM) следует иметь в виду, что они обрабатывают NULL по-особенному. Всегда сверяйтесь с документацией функции для конкретной базы данных.</p>
33
<p>Наконец, при работе с агрегирующими функциями (например, COUNT, AVG, SUM) следует иметь в виду, что они обрабатывают NULL по-особенному. Всегда сверяйтесь с документацией функции для конкретной базы данных.</p>
34
<h2>Выводы</h2>
34
<h2>Выводы</h2>
35
<p>Подведем итоги и сформулируем правила работы с NULL-значениями:</p>
35
<p>Подведем итоги и сформулируем правила работы с NULL-значениями:</p>
36
<ol><li>В SQL существуют различные функции и операторы для обработки NULL значений, такие как COALESCE, IFNULL, NVL, NVL2, и DECODE. Но не все из них поддерживаются во всех СУБД, поэтому важно знать и уметь использовать универсальные функции, такие как COALESCE</li>
36
<ol><li>В SQL существуют различные функции и операторы для обработки NULL значений, такие как COALESCE, IFNULL, NVL, NVL2, и DECODE. Но не все из них поддерживаются во всех СУБД, поэтому важно знать и уметь использовать универсальные функции, такие как COALESCE</li>
37
<li>Значения NULL ведут себя особым образом при выполнении запросов. Например, они не равны ничему (даже другому NULL), их арифметические операции всегда возвращают NULL, и они могут быть расположены в разных местах при сортировке в зависимости от СУБД.</li>
37
<li>Значения NULL ведут себя особым образом при выполнении запросов. Например, они не равны ничему (даже другому NULL), их арифметические операции всегда возвращают NULL, и они могут быть расположены в разных местах при сортировке в зависимости от СУБД.</li>
38
<li>Если столбец - это внешний ключ, то NULL-значения в нем могут нарушать связи между таблицами и приводить к потере информации при выполнении JOIN-запросов</li>
38
<li>Если столбец - это внешний ключ, то NULL-значения в нем могут нарушать связи между таблицами и приводить к потере информации при выполнении JOIN-запросов</li>
39
<li>Агрегирующие функции (COUNT, AVG, SUM) особенным образом обрабатывают NULL-значения, что может привести к искажению результатов агрегации</li>
39
<li>Агрегирующие функции (COUNT, AVG, SUM) особенным образом обрабатывают NULL-значения, что может привести к искажению результатов агрегации</li>
40
</ol>
40
</ol>