SQL и Qt

SELECT, WHERE, ORDER BY: базовые запросы выборки данных

Введение

SELECT — основная команда извлечения данных из таблиц реляционной БД, и в статье разберём её базовый синтаксис: выбор конкретных столбцов, фильтрацию строк через WHERE, и сортировку результата через ORDER BY — фундамент, на котором строятся все более сложные запросы из последующих статей цикла.

Концепция

SELECT определяет, какие столбцы (или вычисляемые выражения) попадут в результат запроса — это не обязательно все столбцы таблицы (SELECT *, обычно нежелательный на практике способ, статья 422). WHERE фильтрует строки исходной таблицы до того, как они попадают в результат, на основе логического условия, проверяемого для каждой строки независимо. ORDER BY определяет порядок строк в итоговом результате — без него СУБД не гарантирует какой-либо конкретный, предсказуемый порядок строк (даже если на практике порядок часто кажется стабильным, это не гарантия, на которую стоит полагаться).

Пример кода: SELECT, WHERE, ORDER BY

-- Выбор конкретных столбцов с фильтрацией и сортировкой
SELECT name, email, registered_at
FROM customers
WHERE registered_at >= '2026-01-01'
ORDER BY registered_at DESC;
-- Комбинация условий через AND/OR, и операторы сравнения
SELECT name, total_amount
FROM orders
WHERE total_amount > 1000 AND order_date >= '2026-01-01'
ORDER BY total_amount DESC, order_date ASC;
-- LIKE для текстового поиска по шаблону, IN для проверки принадлежности набору значений
SELECT name, email
FROM customers
WHERE name LIKE 'Иван%'      -- начинается с "Иван"
  AND id IN (1, 5, 10, 15);   -- id входит в явно перечисленный набор
-- LIMIT для ограничения количества возвращаемых строк (синтаксис варьируется между СУБД)
SELECT name, total_amount
FROM orders
ORDER BY total_amount DESC
LIMIT 10; -- топ-10 заказов по сумме

Пояснения к коду

Условие WHERE registered_at >= '2026-01-01' демонстрирует, что фильтрация происходит до агрегации или иной обработки — каждая строка таблицы customers независимо проверяется на соответствие этому условию, и только прошедшие проверку строки участвуют в дальнейшей обработке запроса (включая последующую сортировку через ORDER BY). ORDER BY total_amount DESC, order_date ASC показывает многоуровневую сортировку — сначала строки упорядочиваются по убыванию суммы заказа, и только строки с равным значением суммы дополнительно упорядочиваются по дате возрастания — это устраняет неоднозначность порядка строк с одинаковым значением первого критерия сортировки.

Подводные камни

  • Использование SELECT * в production-коде вместо явного перечисления нужных столбцов — помимо проблем с производительностью (статья 422), SELECT * делает запрос хрупким к изменениям схемы таблицы (добавление нового столбца в будущем неожиданно меняет структуру результата без изменения самого запроса) и затрудняет понимание того, какие данные запрос реально использует, при чтении кода спустя время.
  • Сравнение с NULL через обычный оператор равенства (WHERE email = NULL) вместо специального синтаксиса IS NULL — NULL в SQL представляет «неизвестное» значение, а не просто «пустое», и сравнение чего-либо с NULL через = всегда даёт результат NULL (не TRUE и не FALSE), что означает, что строка никогда не пройдёт такой фильтр независимо от реального содержимого; эта особенность разбирается подробнее в статье 396.
  • Использование LIKE с шаблоном, начинающимся с % (например, LIKE '%Петров'), без понимания, что это обычно не может использовать стандартный B-tree индекс (статья 413) эффективно, поскольку индекс упорядочен по началу строки, а не по произвольной её части — для частого поиска по такому «обратному» шаблону стоит рассмотреть специализированные индексы полнотекстового поиска (статья 441) вместо обычного индекса с обратным LIKE.
  • Предположение об определённом, стабильном порядке строк результата без явного ORDER BY — без явной сортировки СУБД вольна вернуть строки в любом порядке, который сочла удобным для своего текущего плана выполнения (статья 416), и хотя на практике для простых запросов порядок может казаться стабильным при многократном выполнении, это не гарантированное, документированное поведение, и код, зависящий от порядка строк без явного ORDER BY, может неожиданно «сломаться» при изменении версии СУБД, плана выполнения или просто объёма данных в таблице.