← Назад к вопросам
Какой полный синтаксис у операции SELECT в SQL?
2.2 Middle🔥 211 комментариев
#Базы данных и SQL
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Полный синтаксис SQL оператора SELECT
Это фундаментальный вопрос о структуре SQL запросов. Давайте разберём каждый компонент оператора SELECT в порядке выполнения.
Полный синтаксис SELECT
SELECT [DISTINCT | ALL] [TOP n [WITH TIES]]
column_name, column_name, ..., aggregate_function(column_name)
FROM table_name
[JOIN | LEFT JOIN | RIGHT JOIN | FULL JOIN | CROSS JOIN] table_name
ON join_condition
[WHERE condition]
[GROUP BY column_name]
[HAVING condition]
[ORDER BY column_name [ASC | DESC]]
[LIMIT n] [OFFSET n]
Порядок выполнения SQL запроса (ВАЖНО!)
Это не тот же порядок, что в синтаксисе! SQL выполняет в таком порядке:
1. FROM — выбор таблицы
2. JOIN — объединение таблиц
3. WHERE — фильтрация строк
4. GROUP BY — группировка
5. HAVING — фильтрация групп
6. SELECT — выбор столбцов
7. DISTINCT — удаление дубликатов
8. ORDER BY — сортировка
9. LIMIT/OFFSET — пагинация
Подробное описание каждого компонента
1. SELECT — Выбор столбцов
-- Конкретные столбцы
SELECT id, name, email FROM users;
-- Все столбцы
SELECT * FROM users;
-- С аліасами
SELECT id AS user_id, name AS user_name FROM users;
-- С выражениями
SELECT
id,
UPPER(name) AS name_uppercase,
age * 365 AS days_old,
CASE
WHEN age < 18 THEN 'Minor'
WHEN age < 65 THEN 'Adult'
ELSE 'Senior'
END AS age_group
FROM users;
-- Агрегирующие функции
SELECT
COUNT(*) AS total_users,
AVG(age) AS average_age,
MAX(salary) AS max_salary,
MIN(salary) AS min_salary,
SUM(salary) AS total_salary
FROM users;
2. DISTINCT — Удаление дубликатов
-- Уникальные значения
SELECT DISTINCT country FROM users;
-- DISTINCT на нескольких столбцах
SELECT DISTINCT country, city FROM users;
-- Без DISTINCT (можно написать ALL явно)
SELECT ALL id, name FROM users;
3. TOP / LIMIT — Ограничение количества
-- SQL Server
SELECT TOP 10 * FROM users;
SELECT TOP 10 WITH TIES * FROM users ORDER BY salary;
-- PostgreSQL, MySQL, SQLite
SELECT * FROM users LIMIT 10;
-- С OFFSET (пропуск строк)
SELECT * FROM users LIMIT 10 OFFSET 20; -- Страница 3 (20-29)
-- PostgreSQL
SELECT * FROM users LIMIT 10 OFFSET 20;
4. FROM — Исходная таблица
-- Простая таблица
SELECT * FROM users;
-- С аліасом таблицы
SELECT u.id, u.name FROM users AS u;
SELECT u.id, u.name FROM users u; -- AS опционально
-- Подзапрос в FROM
SELECT * FROM (
SELECT id, name FROM users WHERE status = 'active'
) AS active_users;
5. JOIN — Объединение таблиц
-- INNER JOIN (пересечение)
SELECT u.id, u.name, o.order_id
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
-- LEFT JOIN (все из левой таблицы)
SELECT u.id, u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- RIGHT JOIN (все из правой таблицы)
SELECT u.id, u.name, o.order_id
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
-- FULL JOIN (объединение из обеих таблиц)
SELECT u.id, u.name, o.order_id
FROM users u
FULL OUTER JOIN orders o ON u.id = o.user_id;
-- CROSS JOIN (декартово произведение)
SELECT u.id, c.category_id
FROM users u
CROSS JOIN categories c;
-- Несколько JOIN
SELECT u.id, u.name, o.order_id, p.product_name
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
LEFT JOIN products p ON o.product_id = p.id;
6. WHERE — Фильтрация строк
-- Простое условие
SELECT * FROM users WHERE age > 18;
-- Несколько условий
SELECT * FROM users
WHERE age > 18 AND status = 'active' OR premium = true;
-- IN
SELECT * FROM users WHERE country IN ('USA', 'UK', 'Canada');
-- BETWEEN
SELECT * FROM users WHERE age BETWEEN 18 AND 65;
-- LIKE
SELECT * FROM users WHERE email LIKE '%@gmail.com';
-- IS NULL
SELECT * FROM users WHERE phone IS NULL;
-- Подзапрос в WHERE
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders WHERE total > 1000);
7. GROUP BY — Группировка
-- Группировка по одному столбцу
SELECT country, COUNT(*) AS user_count
FROM users
GROUP BY country;
-- Группировка по нескольким столбцам
SELECT country, status, COUNT(*) AS count
FROM users
GROUP BY country, status;
-- С агрегирующими функциями
SELECT
department,
COUNT(*) AS employee_count,
AVG(salary) AS avg_salary,
MAX(salary) AS max_salary
FROM employees
GROUP BY department;
8. HAVING — Фильтрация групп
-- HAVING применяется ПОСЛЕ GROUP BY
SELECT country, COUNT(*) AS user_count
FROM users
GROUP BY country
HAVING COUNT(*) > 100;
-- WHERE применяется ДО GROUP BY (фильтрует строки)
-- HAVING применяется ПОСЛЕ GROUP BY (фильтрует группы)
SELECT
department,
COUNT(*) AS emp_count,
AVG(salary) AS avg_sal
FROM employees
WHERE hire_date > '2020-01-01' -- Фильтруем строки
GROUP BY department
HAVING AVG(salary) > 50000; -- Фильтруем группы
9. ORDER BY — Сортировка
-- Сортировка по возрастанию (по умолчанию)
SELECT * FROM users ORDER BY name;
-- Сортировка по убыванию
SELECT * FROM users ORDER BY age DESC;
-- Несколько столбцов
SELECT * FROM users
ORDER BY country ASC, name ASC;
-- По номеру столбца (не рекомендуется)
SELECT id, name, age FROM users
ORDER BY 2; -- Сортирует по "name" (второй столбец)
-- По выражению
SELECT * FROM users
ORDER BY age - 18 DESC; -- Сортирует по разнице с 18
10. LIMIT / OFFSET — Пагинация
-- Первые 10 записей
SELECT * FROM users LIMIT 10;
-- С пропуском (OFFSET)
SELECT * FROM users LIMIT 10 OFFSET 20; -- Страница 3
-- В формате "LIMIT count OFFSET skip"
SELECT * FROM users LIMIT 10 OFFSET 30;
-- Альтернативный синтаксис
SELECT * FROM users LIMIT 30, 10; -- LIMIT offset, count (MySQL)
Полный практический пример
SELECT DISTINCT
u.country,
u.status,
COUNT(u.id) AS user_count,
AVG(u.age) AS avg_age,
MAX(o.total) AS max_order_total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at >= '2023-01-01'
AND u.status IN ('active', 'premium')
GROUP BY u.country, u.status
HAVING COUNT(u.id) > 100
AND AVG(u.age) > 25
ORDER BY user_count DESC, u.country ASC
LIMIT 20 OFFSET 0;
Порядок выполнения:
- FROM users u — начинаем с таблицы пользователей
- LEFT JOIN orders — присоединяем заказы
- WHERE — фильтруем (дата создания, статус)
- GROUP BY — группируем по стране и статусу
- HAVING — фильтруем группы (минимум 100 пользователей)
- SELECT — выбираем столбцы и агрегаты
- DISTINCT — удаляем дубликаты
- ORDER BY — сортируем по количеству пользователей
- LIMIT/OFFSET — берём первые 20 записей
Таблица приоритета операторов
| Приоритет | Оператор |
|---|---|
| 1 | FROM |
| 2 | JOIN, ON |
| 3 | WHERE |
| 4 | GROUP BY |
| 5 | HAVING |
| 6 | SELECT |
| 7 | DISTINCT |
| 8 | ORDER BY |
| 9 | LIMIT/OFFSET |
Ключевые моменты
- WHERE фильтрует строки, HAVING фильтрует группы
- GROUP BY требуется, если используешь агрегирующие функции
- ORDER BY выполняется почти в конце, поэтому можешь сортировать по алиасам
- DISTINCT удаляет дубликаты после SELECT
- LIMIT/OFFSET используются для пагинации