← Назад к вопросам

Какой полный синтаксис у операции 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;

Порядок выполнения:

  1. FROM users u — начинаем с таблицы пользователей
  2. LEFT JOIN orders — присоединяем заказы
  3. WHERE — фильтруем (дата создания, статус)
  4. GROUP BY — группируем по стране и статусу
  5. HAVING — фильтруем группы (минимум 100 пользователей)
  6. SELECT — выбираем столбцы и агрегаты
  7. DISTINCT — удаляем дубликаты
  8. ORDER BY — сортируем по количеству пользователей
  9. LIMIT/OFFSET — берём первые 20 записей

Таблица приоритета операторов

ПриоритетОператор
1FROM
2JOIN, ON
3WHERE
4GROUP BY
5HAVING
6SELECT
7DISTINCT
8ORDER BY
9LIMIT/OFFSET

Ключевые моменты

  • WHERE фильтрует строки, HAVING фильтрует группы
  • GROUP BY требуется, если используешь агрегирующие функции
  • ORDER BY выполняется почти в конце, поэтому можешь сортировать по алиасам
  • DISTINCT удаляет дубликаты после SELECT
  • LIMIT/OFFSET используются для пагинации