Команда SELECT в MySQL: синтаксис и примеры запросов от WHERE до JOIN

SELECT читает данные из таблицы MySQL. Разбираем синтаксис по частям: выбор столбцов, фильтр WHERE, сортировку с LIMIT, группировку с HAVING и JOIN двух таблиц.

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

Статью написал:
Ваня Буявец, продюсер, основатель Checkroi
Ваня Буявец
Основатель Checkroi, продюсер, эксперт в выборе онлайн-курсов
Все 2924 статьи автора Подписаться на Телеграм-канал
Одобрено экспертом:
Наташа Буявец, основатель Checkroi, эксперт по онлайн-курсам
Наташа Буявец
Основательница Checkroi, продюсер Youtube-каналов, эксперт по онлайн-курсам
Все 3578 экспертных мнений Подписаться на Телеграм-канал
Обложка: Команда SELECT в MySQL: синтаксис и примеры запросов от WHERE до JOIN

SELECT читает данные из таблицы: вы перечисляете нужные столбцы, после FROM пишете имя таблицы, а условия, сортировку и группировку добавляете по мере надобности. Самый короткий запрос к таблице в MySQL выглядит так: SELECT * FROM customers;. Он вернёт все строки и все столбцы таблицы customers.

Ниже разберём синтаксис команды select по частям: выбор столбцов, фильтр WHERE, сортировку ORDER BY и LIMIT, группировку GROUP BY с HAVING и выборку из двух таблиц через JOIN. Если SQL для вас пока незнакомое слово, начните с обзора языка SQL и того, зачем его учить, а сюда возвращайтесь с первыми запросами.

Все примеры мы запустили на MySQL 8.0.46 с настройками по умолчанию и вставили в статью реальный вывод. В MySQL 8.4 синтаксис SELECT тот же, справочник по нему лежит в официальной документации MySQL (из России этот сайт сейчас часто открывается страницей с ошибкой, поэтому все правила в статье мы проверили запросами). Подборка курсов, где SQL учат с нуля на задачах, есть в нашем каталоге курсов SQL.

CheckroiCheckroiПодборка курсов по MySQL73 курса • 17 школСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Синтаксис SELECT в MySQL и порядок частей запроса

Рой пишет первый запрос SELECT за ноутбуком

Полный оператор select длинный, но в работе нужны семь частей. Порядок, в котором их пишут, фиксирован: документация MySQL прямо требует ставить HAVING после GROUP BY и перед ORDER BY.

SELECT   столбцы или выражения
FROM     таблица
WHERE    условие для строк
GROUP BY столбцы для группировки
HAVING   условие для групп
ORDER BY столбцы для сортировки
LIMIT    сколько строк вернуть;

Обязателен только SELECT. Остальные части добавляются, когда нужны: простой запрос часто состоит из SELECT, FROM и WHERE.

Пишут запрос в одном порядке, а логически база обрабатывает его в другом. Из-за этой разницы новички чаще всего и ошибаются, поэтому сохраните таблицу.

Шаг Часть запроса Что делает
1 FROM, JOIN Берёт таблицы и соединяет их
2 WHERE Отбрасывает строки, которые не подходят под условие
3 GROUP BY Собирает оставшиеся строки в группы
4 HAVING Отбрасывает группы
5 SELECT Считает выражения и присваивает псевдонимы
6 ORDER BY Сортирует результат
7 LIMIT Отрезает нужное число строк

Отсюда правило: псевдоним из SELECT нельзя использовать в WHERE, потому что на шаге 2 его ещё не существует. В ORDER BY, GROUP BY и HAVING псевдоним работать будет, это тоже написано в разделе документации о псевдонимах.

Учебные таблицы для примеров

Чтобы повторить запросы у себя, создайте две таблицы: клиентов и заказов. Подойдёт любая база MySQL, хоть локальная, хоть в облаке. Запросы можно выполнять в консольном клиенте mysql, в MySQL Workbench или в DBeaver, по нему у нас есть разбор подключения DBeaver к базе и частых ошибок.

CREATE TABLE customers (
  id   INT PRIMARY KEY,
  name VARCHAR(50),
  city VARCHAR(50)
);

CREATE TABLE orders (
  id          INT PRIMARY KEY,
  customer_id INT,
  product     VARCHAR(50),
  amount      DECIMAL(10,2),
  created_at  DATE,
  status      VARCHAR(20)
);

INSERT INTO customers VALUES
  (1, 'Анна', 'Москва'),
  (2, 'Борис', 'Казань'),
  (3, 'Вера', 'Москва'),
  (4, 'Глеб', NULL);

INSERT INTO orders VALUES
  (101, 1, 'Ноутбук',    85000, '2026-09-02', 'paid'),
  (102, 2, 'Мышь',        1500, '2026-09-05', 'paid'),
  (103, 1, 'Монитор',    23000, '2026-09-11', 'cancelled'),
  (104, 3, 'Клавиатура',  4200, '2026-09-18', 'paid'),
  (105, 2, 'Наушники',    7900, '2026-10-01', 'new'),
  (106, 3, 'Ноутбук',    91000, '2026-10-03', 'paid');

У Глеба город не указан, поле хранит NULL. Это сделано нарочно: с NULL чаще всего ошибаются, и ниже это видно на живом примере.

Канал основателя Checkroi Вани Буявца3 700 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединиться

Как выбрать столбцы: SELECT *, список полей и псевдонимы

Звёздочка возвращает все столбцы в том порядке, в каком они объявлены в таблице.

SELECT * FROM customers;

+----+-------+--------+
| id | name  | city   |
+----+-------+--------+
|  1 | Анна  | Москва |
|  2 | Борис | Казань |
|  3 | Вера  | Москва |
|  4 | Глеб  | NULL   |
+----+-------+--------+

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

SELECT product, amount FROM orders;

Псевдонимы и вычисления

В списке SELECT можно считать: умножать, склеивать строки, вызывать функции. Ключевое слово AS даёт столбцу понятное имя.

SELECT product AS товар, amount * 0.8 AS со_скидкой
FROM orders
WHERE id = 101;

+---------+------------+
| товар   | со_скидкой |
+---------+------------+
| Ноутбук |  68000.000 |
+---------+------------+

Формально AS можно не писать, но справочник по SELECT советует ставить его всегда. Без него забытая запятая между двумя столбцами молча превращает второй столбец в псевдоним первого, и запрос возвращает не то, что вы ждали.

DISTINCT и SELECT без таблицы

DISTINCT убирает повторы. NULL при этом считается отдельным значением и попадает в результат:

SELECT DISTINCT city FROM customers;

+--------+
| city   |
+--------+
| Москва |
| Казань |
| NULL   |
+--------+

А ещё SELECT умеет работать вообще без FROM. Запрос SELECT 1 часто используют, чтобы проверить, что соединение с базой живо:

SELECT 1, 2 + 2 AS sum;

+---+-----+
| 1 | sum |
+---+-----+
| 1 |   4 |
+---+-----+

Фильтрация строк через WHERE

WHERE оставляет только строки, для которых условие истинно. Условия соединяют через AND и OR, а скобки задают, что проверять первым. Из таких фильтров состоит большая часть рабочего дня SQL-аналитика: выгрузить заказы за период, отобрать клиентов из одного города, найти пустые поля.

SELECT id, product, amount
FROM orders
WHERE status = 'paid' AND amount > 5000;

+-----+---------+----------+
| id  | product | amount   |
+-----+---------+----------+
| 101 | Ноутбук | 85000.00 |
| 106 | Ноутбук | 91000.00 |
+-----+---------+----------+

Кроме обычных сравнений, в WHERE постоянно встречаются ещё четыре оператора:

Оператор Пример Что вернул на наших данных
IN status IN ('new', 'cancelled') Заказы 103 и 105
BETWEEN created_at BETWEEN '2026-09-01' AND '2026-09-30' Четыре сентябрьских заказа, 101–104; границы входят в диапазон
LIKE name LIKE 'В%' Вера: % означает любое число любых символов
IS NULL city IS NULL Глеб

Почему city = NULL ничего не находит

Запрос SELECT name FROM customers WHERE city = NULL; вернёт пустой результат, хотя Глеб в таблице есть. Любое сравнение с NULL через =, < или <> даёт NULL, а не «истину», поэтому строка не проходит фильтр.

Решение: проверять пустое значение только через IS NULL и IS NOT NULL. Так написано и в разделе документации о работе с NULL.

Тот же эффект бывает с отрицанием. Мы ждали, что WHERE city <> 'Москва' вернёт Бориса и Глеба, а получили только Бориса: строка с NULL снова выпала. Если она нужна, добавьте OR city IS NULL, а остальные подвохи пустых значений собраны в разборе NULL в SQL.

Сортировка ORDER BY и ограничение LIMIT

ORDER BY сортирует по одному или нескольким столбцам, DESC разворачивает порядок. LIMIT отрезает первые строки результата, и вместе они дают классический «топ».

SELECT id, product, amount
FROM orders
ORDER BY amount DESC
LIMIT 3;

+-----+---------+----------+
| id  | product | amount   |
+-----+---------+----------+
| 106 | Ноутбук | 91000.00 |
| 101 | Ноутбук | 85000.00 |
| 103 | Монитор | 23000.00 |
+-----+---------+----------+

Для постраничного вывода добавляют OFFSET: сколько строк пропустить. Запрос ниже показывает вторую «страницу» по две строки.

SELECT id, product, amount
FROM orders
ORDER BY amount DESC
LIMIT 2 OFFSET 2;

+-----+----------+----------+
| id  | product  | amount   |
+-----+----------+----------+
| 103 | Монитор  | 23000.00 |
| 105 | Наушники |  7900.00 |
+-----+----------+----------+

MySQL понимает и короткую запись LIMIT 2, 2: первое число означает смещение, второе количество строк. Вариант с OFFSET читается проще и работает так же в PostgreSQL.

LIMIT без ORDER BY не гарантирует, какие строки вы получите. Даже с ORDER BY строки с одинаковым значением сортировки MySQL вправе отдавать в любом порядке. Чтобы страницы не «прыгали», добавьте в сортировку уникальный столбец: ORDER BY amount DESC, id. Этот совет есть в описании оптимизации LIMIT.

Группировка GROUP BY, агрегатные функции и HAVING

Рой радуется, что запрос с группировкой вернул верный итог

GROUP BY собирает строки с одинаковым значением в одну группу, а агрегатные функции считают по группе итог: COUNT считает строки, SUM складывает, AVG даёт среднее, MIN и MAX находят крайние значения.

SELECT status, COUNT(*) AS заказов, SUM(amount) AS сумма
FROM orders
GROUP BY status
ORDER BY сумма DESC;

+-----------+---------+-----------+
| status    | заказов | сумма     |
+-----------+---------+-----------+
| paid      |       4 | 181700.00 |
| cancelled |       1 |  23000.00 |
| new       |       1 |   7900.00 |
+-----------+---------+-----------+

Такие сводки по статусам и периодам потом превращаются в графики: этим занимается BI-аналитик, и GROUP BY у него в каждом втором запросе.

Обратите внимание на COUNT. COUNT(*) считает все строки, а COUNT(city) только те, где город заполнен, так работает функция COUNT по описанию в справочнике. На таблице клиентов первый вернул 4, второй 3.

Чем WHERE отличается от HAVING

WHERE фильтрует строки до группировки, HAVING фильтрует уже готовые группы. Запрос ниже сначала оставляет оплаченные заказы, потом складывает их по клиентам и показывает тех, кто заплатил больше 50 000 ₽.

SELECT customer_id, SUM(amount) AS оплачено
FROM orders
WHERE status = 'paid'
GROUP BY customer_id
HAVING SUM(amount) > 50000;

+-------------+----------+
| customer_id | оплачено |
+-------------+----------+
|           1 | 85000.00 |
|           3 | 95200.00 |
+-------------+----------+

Условие на сумму в WHERE поставить нельзя: на этом шаге групп ещё нет. Разницу между WHERE и HAVING регулярно спрашивают на собеседованиях, ещё три типовые задачи разобраны в статье про собеседование на аналитика данных.

Ваня БуявецКанал основателя Checkroi Вани БуявцаЗабирайте промпты и обучение по нейросетям в моём Телеграм-каналеБольше 3 700 человек уже применяют Claude Code, ChatGPT и другие нейросети в работе, учёбе, бизнесе и жизниПерейти в канал

SELECT из нескольких таблиц: JOIN и подзапрос

Две таблицы базы данных соединены по общему полю

Данные о клиенте и о заказе лежат в разных таблицах, а в отчёте их нужно увидеть рядом. Для этого таблицы соединяют по общему полю: у нас это orders.customer_id и customers.id.

SELECT c.name, o.product, o.amount
FROM orders AS o
INNER JOIN customers AS c ON c.id = o.customer_id
WHERE o.status = 'paid'
ORDER BY o.amount DESC;

+-------+------------+----------+
| name  | product    | amount   |
+-------+------------+----------+
| Вера  | Ноутбук    | 91000.00 |
| Анна  | Ноутбук    | 85000.00 |
| Вера  | Клавиатура |  4200.00 |
| Борис | Мышь       |  1500.00 |
+-------+------------+----------+

Короткие имена o и c здесь псевдонимы таблиц. Без них пришлось бы каждый раз писать полное имя, а в запросе с тремя-четырьмя таблицами это быстро становится нечитаемым.

INNER JOIN и LEFT JOIN

INNER JOIN оставляет только пары, у которых нашлось совпадение. LEFT JOIN сохраняет все строки левой таблицы, даже если справа для них ничего нет. Так видно клиентов без заказов:

SELECT c.name, COUNT(o.id) AS заказов
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY c.id;

+-------+---------+
| name  | заказов |
+-------+---------+
| Анна  |       2 |
| Борис |       2 |
| Вера  |       2 |
| Глеб  |       0 |
+-------+---------+

С INNER JOIN Глеб из этого отчёта просто исчез бы. Поэтому считаем COUNT(o.id), а не COUNT(*): у Глеба строка есть, но поля заказа в ней пустые, и звёздочка показала бы единицу.

Подзапрос в WHERE

Иногда проще не соединять таблицы, а подставить результат одного SELECT в другой. Соединения и подзапросы подробно разбирают на курсах по MySQL, здесь покажем базовый вариант. Найдём клиентов, у которых был заказ дороже 50 000 ₽:

SELECT name
FROM customers
WHERE id IN (SELECT customer_id FROM orders WHERE amount > 50000);

+------+
| name |
+------+
| Анна |
| Вера |
+------+

Частые ошибки в запросах SELECT и что с ними делать

Все ошибки ниже мы получили сами на тех же таблицах, текст сообщений скопирован из вывода MySQL.

  1. ERROR 1055 … incompatible with sql_mode=only_full_group_by. Причина: в SELECT есть столбец, которого нет в GROUP BY и который не посчитан агрегатной функцией. Например, SELECT customer_id, product, SUM(amount) FROM orders GROUP BY customer_id: у одного клиента несколько товаров, и базе непонятно, какой показать. Решение: добавить столбец в GROUP BY, обернуть его в агрегат или, если значение в группе точно одно, в ANY_VALUE(). Режим включён по умолчанию, подробности в разделе о GROUP BY.
  2. ERROR 1054 Unknown column ‘со_скидкой’ in ‘where clause’. Причина: псевдоним из SELECT использован в WHERE. Решение: повторить в условии само выражение, WHERE amount * 0.8 > 1000, или перенести фильтр в HAVING.
  3. Пустой результат на city = NULL. Причина разобрана выше. Решение: IS NULL, а в условиях с <> помнить, что NULL-строки выпадут.
  4. ERROR 1054 Unknown column ‘Мышь’. Причина: строка в двойных кавычках, а на сервере включён режим ANSI_QUOTES, в котором двойные кавычки означают имя столбца. С настройками по умолчанию MySQL принимает обе кавычки, поэтому запрос может работать у вас и ломаться на другом сервере. Решение: строки всегда в одинарных кавычках, это правило строковых литералов MySQL.
  5. Каждый раз разные строки в выдаче с LIMIT. Причина: нет ORDER BY или сортировка по неуникальному полю. Решение: добавить в конец сортировки id.

Как тренироваться писать запросы SELECT

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

  • Своя учебная база. Таблицы из этой статьи создаются за минуту. Добавьте третью, например товары, и попробуйте ответить на вопросы бизнеса: кто из клиентов вернулся повторно, какой товар отменяют чаще остальных.
  • Сначала строки, потом итоги. Пишите запрос по шагам: SELECT * с WHERE, проверили строки, затем GROUP BY. Ошибку в данных на маленьком результате видно сразу.
  • План запроса. Когда запросы станут тяжелее, допишите перед SELECT слово EXPLAIN: MySQL покажет, какие индексы он использует.

Если SQL нужен для смены профессии, посмотрите, как SELECT вписывается в работу целиком, в нашем плане как стать SQL-разработчиком.

Где освоить SQL и MySQL системно

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

В каталоге есть курсы по SQL от разных школ с ценами и отзывами, среди них программы с упором на MySQL. Вот курсы с самым высоким рейтингом:

КурсШколаСтоимость со скидкойВ рассрочкуДлитель­ностьОбзор курса от Checkroi
Нейросети для рабочих задач
Перейти на сайт курса
SkillboxSkillbox31 290 ₽ - 1 месяцОбзор курса
SQL-разработчик: тариф PRO
Перейти на сайт курса
Академия ЭдюсонЭдюсон89 900 ₽7491 ₽/мес.2 месяцаОбзор курса
SQL-разработчик: тариф Базовый
Перейти на сайт курса
Академия ЭдюсонЭдюсон79 900 ₽3329 ₽/мес.3 месяцаОбзор курса
SQL для анализа данных
Перейти на сайт курса
SkillboxSkillbox50 828 ₽6203 ₽/мес.2 месяцаОбзор курса
SQL с нуляSkyproSkypro134 640 ₽5500 ₽/мес.12 месяцевОбзор курса

Больше программ — в полном каталоге курсов по SQL

Часто задаваемые вопросы

Что значит SELECT в SQL?

SELECT переводится с английского как «выбрать». Это команда чтения: она возвращает строки из таблицы в виде результата и сами данные не меняет. Синтаксис по частям разобран в начале статьи.

Что означает SELECT * FROM?

Звёздочка означает «все столбцы», а после FROM указывают таблицу. Запрос SELECT * FROM orders вернёт всю таблицу заказов. Для рабочих запросов лучше перечислять нужные столбцы явно.

Что делает запрос SELECT 1?

Он возвращает одну строку с единицей и не обращается ни к одной таблице. Так проверяют, что соединение с базой работает. В подзапросах EXISTS тоже часто пишут SELECT 1, потому что там важен сам факт, что строка нашлась.

С какой командой всегда используется SELECT?

В MySQL обязателен только сам SELECT. FROM нужен, когда вы читаете из таблицы, а запрос вроде SELECT 2 + 2 работает и без него.

Чем WHERE отличается от HAVING?

WHERE отбирает строки до группировки, HAVING отбирает группы после GROUP BY. Поэтому условие на сумму или количество пишут в HAVING: в момент работы WHERE групп ещё нет.

Как вывести первые 10 строк таблицы в MySQL?

Добавьте в конец запроса LIMIT 10 и обязательно ORDER BY. Без сортировки MySQL не гарантирует, какие именно десять строк вернутся.

Читайте Checkroi первым в Google
Добавьте Checkroi в избранные источники — и наши разборы курсов и обзоры школ будут показываться выше в вашей выдаче Google.
Оставить комментарий
0 комментариев
Форма комментария

Оставьте комментарий

Напишите, что думаете. Нам важно ваше мнение!