ORDER BY — сортируем строки

Данные: таблица employees
idfirst_namedepartment_idsalary
1Иван170000
2Анна265000
3Сергей172000
4Елена380000
5Дмитрий260000
Шаг 1. Берём ВСЕ строки из employees.
Шаг 2. Сортируем их по salary по убыванию (DESC).
SELECT id, first_name, department_id, salary
FROM employees
ORDER BY salary DESC;
Результат:
idfirst_namedepartment_idsalary
4Елена380000
3Сергей172000
1Иван170000
2Анна265000
5Дмитрий260000
Комбинированная сортировка: сначала по отделу ↑, внутри — по зарплате ↓.
SELECT id, first_name, department_id, salary
FROM employees
ORDER BY department_id ASC, salary DESC;

GROUP BY — объединяем строки в группы

Данные те же (employees).
idfirst_namedepartment_idsalary
1Иван170000
2Анна265000
3Сергей172000
4Елена380000
5Дмитрий260000
Шаг 1. Делим строки на группы по department_id.
Шаг 2. Для каждой группы считаем COUNT(*) и AVG(salary).
SELECT
  department_id,
  COUNT(*)       AS employee_count,
  AVG(salary)    AS avg_salary
FROM employees
GROUP BY department_id;
Результат:
department_idemployee_countavg_salary
1271000.00
2262500.00
3180000.00
Важно: в SELECT можно выводить только поля из GROUP BY или агрегаты.

HAVING — фильтруем уже сформированные группы

Шаг 1. Сначала формируем группы по department_id.
Шаг 2. Считаем размер группы COUNT(*).
Шаг 3. Оставляем только группы, где сотрудников больше 1 — это делает HAVING.
SELECT
  department_id,
  COUNT(*) AS employee_count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 1;
Результат:
department_idemployee_count
12
22
WHERE vs HAVING: WHERE фильтрует отдельные строки до группировки, HAVING — готовые группы после GROUP BY.
Комбо-пример: сначала выберем только отделы 1 и 2 (WHERE), потом оставим группы с ср. зарплатой > 65k (HAVING).
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
WHERE department_id IN (1,2)          -- фильтр строк ДО группировки
GROUP BY department_id
HAVING AVG(salary) > 65000;           -- фильтр групп ПОСЛЕ группировки
Результат:
department_idavg_salary
171000.00