6 скрытых ошибок SQL, которых следует избегать

Они летают под радаром и доставят вам неприятности

SQL великолепен. Он удобен для чтения и эффективен. Подобрать довольно легко.

К сожалению, очень легко допустить серьезные ошибки в SQL. Те, которые не выделяются, не попадают в руки редактора и не вызывают головной боли.

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

1. Нули в операциях

SQL имеет большое количество общих и полезных операторов для арифметики (например, +, -), сравнения (например, ›,‹) и логики (например, Not, in).

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

Вот пара примеров:

а. Добавление столбцов

Допустим, у нас есть один столбец с продажами за 2019 год и один с продажами за 2020 год. И в одной из наших строк за 2019 год указано пустое значение.

Когда мы складываем их вместе, мы получаем нуль:

Это плохие новости. Мы могли бы знать, что null нужно рассматривать как 0, но SQL этого не делает.

б. Оператор «Not In»

Теперь предположим, что у нас есть таблица с результатами опроса о продукте. И мы хотим исключить только очень плохие или очень хорошие отзывы.

Когда мы запрашиваем рейтинг, не входящий в («Очень хорошо», «Очень плохо»), мы получаем следующее:

Мы можем ожидать возврата значений NULL (в конце концов, NULL отсутствует в списке, который мы предоставили), но SQL исключит их из набора результатов.

Исправление: всякий раз, когда мы выполняем операции, мы должны быть осведомлены о любых нулевых значениях в наших столбцах. Если мы хотим, чтобы к ним относились как к другому значению, мы можем легко это сделать с помощью оператора «coalesce»:

coalesce(rating, ‘’) 

2. Нули в агрегатах

Это проблема, противоположная описанной выше. Когда мы запускаем функции агрегирования, SQL игнорирует значения NULL. Во многих случаях это желательно.

Но что, если значения NULL действительно нули?

Например, давайте посчитаем средние продажи в 2020 году:

В этом случае SQL исключает нулевое значение и вычисляет 410/4 = 102,5 вместо 410/5 = 82.

Это очень легко пропустить - 102,5 звучит как реальная, вполне разумная величина.

Исправление: то же, что и №1. Давайте объединим нули, если они действительно означают 0.

3. Неправильные присоединения

Объединения - это ключевая функция SQL, которая помогает нам объединять данные из двух таблиц.

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

Например, предположим, что у нас есть таблица географии и таблица продаж, и мы хотим отправить список всех контактов и продаж нашей маркетинговой команде.

Левое соединение дает нам все наши контакты и их продажи, но внутреннее соединение отбрасывает все контакты, у которых нет продаж:

Если мы используем в этом случае внутреннее соединение, мы теряем данные, которые могут быть важны (возможно, маркетингу нужно ориентироваться на потенциальных клиентов!).

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

Для получения дополнительной информации ознакомьтесь с моим вводным сообщением о соединении данных:



Между прочим, если мы все же проходим с помощью левого соединения, мы должны убедиться, что наш столбец продаж объединен с 0, иначе мы можем столкнуться с проблемой №1 или №2, описанной выше!

4. Повторяющийся ключ в правой таблице.

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

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

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

Если мы присоединяемся в состоянии, мы получаем дубликаты контактов:

Решение. Убедитесь, что мы знаем, являются ли столбцы правого ключа соединения отдельными или нет. Простой способ проверить - запустить подсчет и подсчет отдельно и убедиться, что они одинаковы:

#these will be equal if there are no duplicates
select count(state), count(distinct state) from mytable;

5. Проблемы с приоритетом операторов (помните о своих «и» и «или»!)

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

Самый распространенный пример: когда мы пишем SQL-запросы, «И» обрабатывается раньше «ИЛИ».

Допустим, у нас есть таблица с продажами клиентов и сегментом, и мы хотим вернуть клиентов в сегменте A или сегменте B, у которых также должны быть продажи ›100.

Если мы напишем наш запрос, не обращая внимания на приоритет, мы получим:

Обратите внимание, что запись клиента 1 возвращается, даже если у нее продажи ниже 100. Это потому, что запрос сначала разрешает оператор «и».

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

Исправление: всегда используйте круглые скобки, когда мы используем более одного оператора. Это предотвращает ошибки и делает наш код более читабельным.

6. Опущена запятая.

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

Для Postgres нам не нужно включать ключевое слово as при именовании столбцов.

Это означает, что если мы удалим запятую из нашего запроса, SQL переименует столбец перед запятой с именем столбца после столбца:

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

Исправление: внимательно проверьте нашу инструкцию select перед запуском, чтобы убедиться, что мы не потеряли запятые.

Заключительные мысли

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

P.S. → если вы хотите узнать больше о SQL, Python и науке о данных, подпишитесь на мой бесплатный список рассылки.