tgoop.com/big_data_systems_analysis/192
Create:
Last Update:
Last Update:
Иногда приходится разбирать чужие sql-запросы и периодически сталкиваюсь с различными ошибками. Сегодня хочу рассказать о трёх наиболее распространённых.
Некорректная работа с NULL
Я уже много раз писала, NULL — не просто пустота, это неизвестность. Поэтому нельзя сравнивать с NULL в лоб. Запрос вам ошибку не выдаст, но отработает некорректно.
-- неправильно:
SELECT * FROM users WHERE age = NULL;
SELECT * FROM users WHERE age != NULL;
-- правильно:
SELECT * FROM users WHERE age IS NULL;
SELECT * FROM users WHERE age IS NOT NULL;
Также при подсчёте количества строк
COUNT(column_name)
пропустит все NULL-значения. Поэтому если нужно посчитать прям вообще всё используйте COUNT(*).
-- считает количество заполненных номеров:
SELECT COUNT(phone) FROM users;
-- считает все строки, в том числе с NULL:
SELECT COUNT(*) FROM users;
Больше про #null я писала в постах с соответствующим тегом) на собесах часто про это спрашивают, но уделить внимание теме, конечно же, стоит не только поэтому.
Неправильное использование оператора BETWEEN
Ещё часто вижу, как забывают об особеннстях BETWEEN, забывая, что он включает и верхнюю, и нижнюю границы диапазона. Это может привести к дублированию данных или их пропуску при последовательной выборке.
-- пример кода с ошибкой:
-- выборка за 1 марта о полю типа дата-время
SELECT * FROM orders WHERE order_dttm BETWEEN '2024-03-01' AND '2024-03-02';
-- Выборка за 2 марта
SELECT * FROM orders WHERE order_dttm BETWEEN '2024-03-02' AND '2024-03-03';
В этом примере заказы, созданные ровно в полночь 2 марта (2024-03-02 00:00:00), будут включены в обе выборки! Лучше использовать явные полуинтервалы:
-- правильно:
-- выборка за 1 марта
SELECT * FROM orders WHERE order_dttm >= '2024-03-01' AND order_dttm < '2024-03-02';
-- выборка за 2 марта
SELECT * FROM orders WHERE order_dttm >= '2024-03-02' AND order_dttm < '2024-03-03';
Но если сильно хочется BETWEEN, то:
-- выборка за 1 марта
SELECT * FROM orders WHERE order_dttm BETWEEN '2024-03-01 00:00:00' AND '2024-03-01 23:59:59';
-- выборка за 2 марта
SELECT * FROM orders WHERE order_dttm BETWEEN '2024-03-01 00:00:00.000' AND '2024-03-01 23:59:59.999';
Да, про миллисекунды забывать не нужно, а то можно что-то потерять. И всё-таки проще использовать полуинтервалы)
Ошибки в логических операторах
Ещё часто забывают про приоритеты при использовании AND и OR в одном условии. В SQL сначала выполняются все AND, а затем уже OR.
Например, нужно найти все транзакции на сумму больше 100.000, которые имеют статус "completed" и при этом либо от премиум-пользователя, либо оплачены кредитной картой.
-- неправильно:
SELECT * FROM transactions
WHERE amount > 100000
AND status = 'completed'
AND user_type = 'premium' OR payment_method = 'credit_card'
По правилам SQL операторы AND приоритетнее. Поэтому запрос интерпретируется так:
SELECT * FROM transactions
WHERE (status = 'completed' AND amount > 100000 AND user_type = 'premium')
OR (payment_method = 'credit_card')
То есть мы получим все завершённые транзакции премиум-пользователей с суммой больше 100000, плюс абсолютно все транзакции с кредитных карт (даже незавершённые и с маленькими суммами).
Так мы получим именно то, что хотели:
-- правильно:
SELECT * FROM transactions
WHERE status = 'completed'
AND amount > 100000
AND (user_type = 'premium' OR payment_method = 'credit_card')
В целом, проще лишний раз указать скобки, чем запутаться и получить ошибочный результат.
Кому-то кажется очевидным, но такие вещи, действительно, встречаются. А с какими ошибками в sql вы часто сталкиваетесь?
#sql
BY В мире больших данных
Share with your friend now:
tgoop.com/big_data_systems_analysis/192