29/10/2026

Основы и базовые выборки

Диалект — PostgreSQL. Таблицы, запросы, WHERE, ORDER BY, LIMIT.

0. С чего начинается SQL: таблица и запрос

Реляционная база данных — это набор таблиц, связанных между собой.

Таблица = сущность (например, «сотрудники»). Строка (запись) = один объект (один сотрудник). Столбец (поле) = характеристика (имя, зарплата). SQL = язык, на котором мы просим базу эти данные найти, посчитать или изменить.

Наша учебная таблица employees

idnamedepartmentcitysalarybonus
1АннаITМосква12000020000
2ИванПродажиСПб80000NULL
3МарияITКазань13000025000
4АндрейМаркетингМосква70000NULL
5ЕленаПродажиСПб9000010000
6ПавелITМосква110000NULL
7ДарьяМаркетингКазань750005000
8СергейПродажиМосква85000NULL

Обрати внимание на NULL в bonus. Это не ноль и не пустая строка, а «значения нет». С ним мы разберёмся отдельно — это частая причина ошибок.

Два правила оформления

  1. Ключевые слова (SELECT, FROM, WHERE) пишут заглавными — это просто договорённость для читаемости.
  2. Запрос заканчивается ;. Строковые значения берём в одинарные кавычки: 'IT'. Двойные кавычки — для имён таблиц и столбцов.

1. SELECT и FROM: достаём данные

FROM — откуда берём, SELECT — что берём.

SELECT name, salary
FROM employees;

Результат — 8 строк с двумя столбцами.

Все столбцы сразу

SELECT *
FROM employees;

* удобно для быстрого просмотра, но в реальных проектах лучше перечислять поля явно: так запрос понятнее и не тащит лишние данные.

Псевдонимы: AS

Можно переименовать столбец в результате (не в самой таблице!):

SELECT name AS employee_name, salary AS monthly_salary
FROM employees;

Слово AS необязательное: salary monthly_salary работает так же.

💡 Важный нюанс PostgreSQL: псевдоним нельзя использовать в WHERE:

-- Так НЕ работает:
SELECT salary AS pay FROM employees WHERE pay > 100000;

Причина станет понятна в разделе про порядок выполнения.

2. DISTINCT: убираем дубликаты

Посмотрим, в каких городах работают сотрудники:

SELECT city
FROM employees;

Получим: Москва, СПб, Казань, Москва, СПб, Москва, Казань, Москва.

SELECT DISTINCT city
FROM employees;

Получим: Москва, СПб, Казань — по одному разу.

DISTINCT действует по всей комбинации выбранных полей:

SELECT DISTINCT department, city
FROM employees;

Здесь дубль уберётся только если совпадают и отдел, и город одновременно.

3. WHERE: оставляем нужные строки

WHERE фильтрует строки до того, как они попадут в результат. Условие должно быть истинным (TRUE).

SELECT name, salary
FROM employees
WHERE salary > 100000;

→ Анна (120 000), Мария (130 000), Павел (110 000).

Операторы сравнения: =, <> (или !=), >, <, >=, <=.

⚠️ Одно = — это сравнение, а не присваивание.

AND, OR, NOT: комбинируем условия

И то, и другое (AND):

SELECT name, salary
FROM employees
WHERE department = 'IT'
  AND salary >= 110000;

→ Анна, Мария, Павел.

Хотя бы одно (OR):

SELECT name, city
FROM employees
WHERE city = 'Казань'
   OR salary > 100000;

→ Анна, Мария, Павел, Дарья.

Инверсия (NOT):

SELECT name
FROM employees
WHERE NOT department = 'IT';

→ все, кроме сотрудников IT.

Скобки решают всё

AND имеет больший приоритет, чем OR. Без скобок легко получить не то:

-- Непонятно и рискованно:
WHERE department = 'IT' OR department = 'Маркетинг' AND city = 'Москва'

-- Явно и правильно:
WHERE (department = 'IT' OR department = 'Маркетинг')
  AND city = 'Москва';

Второй вариант: Анна, Павел, Андрей. Всегда используй скобки, когда мешаешь AND и OR.

4. IN, BETWEEN, LIKE, IS NULL

Это сокращённые и более удобные формы условий.

IN — значение из списка

Вместо city = 'Москва' OR city = 'Казань':

SELECT name, city
FROM employees
WHERE city IN ('Москва', 'Казань');

Работает и наоборот:

WHERE department NOT IN ('IT', 'Продажи')

→ только Маркетинг.

BETWEEN — диапазон, включая границы

SELECT name, salary
FROM employees
WHERE salary BETWEEN 80000 AND 100000;

→ Иван (80 000), Елена (90 000), Сергей (85 000).

Это то же самое, что salary >= 80000 AND salary <= 100000. Работает не только с числами, но и с датами.

LIKE — поиск по шаблону

Два спецсимвола:

  • % — любое количество символов, в том числе ноль;
  • _ — ровно один символ.
-- Имена, начинающиеся на «А»
SELECT name FROM employees WHERE name LIKE 'А%';

→ Анна, Андрей.

-- Третья и четвёртая буквы — «ар»
SELECT name FROM employees WHERE name LIKE '_ар%';

→ Мария, Дарья.

В PostgreSQL LIKE чувствителен к регистру. Для поиска без учёта регистра есть ILIKE:

WHERE name ILIKE 'а%';

IS NULL / IS NOT NULL — проверка на отсутствие значения

Главная ловушка этапа: сравнивать с NULL через = нельзя.

-- НЕ РАБОТАЕТ (вернёт ноль строк):
WHERE bonus = NULL;

-- ПРАВИЛЬНО:
SELECT name FROM employees WHERE bonus IS NULL;

→ Иван, Андрей, Павел, Сергей.

А наличие премии:

SELECT name, bonus
FROM employees
WHERE bonus IS NOT NULL;

→ Анна, Мария, Елена, Дарья.

Почему так: NULL — это «неизвестно», а сравнение с неизвестным даёт не истину, а UNKNOWN, и такая строка в результат не попадает. То же касается NOT IN со списком, содержащим NULL, — запомни на будущее.

5. ORDER BY: сортировка

Без ORDER BY порядок строк не гарантирован. Даже если кажется, что они идут по id, не рассчитывай на это.

-- По зарплате от большой к маленькой
SELECT name, salary
FROM employees
ORDER BY salary DESC;
  • ASC — по возрастанию (по умолчанию);
  • DESC — по убыванию.

Несколько уровней сортировки

SELECT department, name, salary
FROM employees
ORDER BY department ASC, salary DESC;

Сначала группируем визуально по отделам (буквенный порядок), внутри отдела — зарплата по убыванию.

Сортировать можно и по полю, которого нет в SELECT: SELECT name FROM employees ORDER BY salary DESC; — это нормально.

С NULL

В PostgreSQL при ASC они уходят в конец, при DESC — в начало. Управлять этим можно явно:

ORDER BY bonus DESC NULLS LAST;

6. LIMIT и OFFSET: ограничиваем выдачу

Топ-3 по зарплате

SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 3;

→ Мария (130 000), Анна (120 000), Павел (110 000).

⚠️ Без ORDER BYLIMIT 3 вернёт «какие-то три строки», а не «три самые большие». LIMIT почти всегда пишется вместе с ORDER BY.

Пагинация (как страницы в интерфейсе) — через OFFSET

SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 2 OFFSET 2;

Пропускаем первых двух, берём следующих двух → Елена (90 000), Сергей (85 000).

Логика: OFFSET — сколько пропустить, LIMIT — сколько взять.

7. Самый важный момент: порядок выполнения

Мы пишем SELECT первым, но база выполняет запрос не в том порядке:

ЭтапКлаузаОписание
1FROM→ берём таблицу
2WHERE→ отбрасываем лишние строки
3GROUP BY→ группируем
4HAVING→ фильтруем группы
5SELECT→ считаем/выбираем столбцы, применяем DISTINCT
6ORDER BY→ сортируем готовый результат
7LIMIT→ обрезаем

Отсюда три следствия, которые снимут 90% твоих ошибок:

  1. В WHERE нельзя использовать псевдоним из SELECT — его ещё не существует.
  2. В WHERE нельзя использовать агрегаты вроде SUM() — для этого будет HAVING.
  3. ORDER BY работает уже с результатом, поэтому там псевдонимы как раз разрешены.

8. Практика: 8 задач на этот этап

Попробуй решить самостоятельно, не подглядывая ниже.

  1. Выведи имя, отдел и зарплату всех сотрудников.
  2. Выведи только уникальные отделы.
  3. Найди сотрудников из Москвы с зарплатой больше 85 000.
  4. Найди сотрудников отделов «IT» и «Маркетинг» (через IN).
  5. Найди зарплату в диапазоне от 75 000 до 90 000 включительно.
  6. Найди сотрудников без премии (NULL).
  7. Выведи топ-3 сотрудников по зарплате по возрастанию (то есть самых низкооплачиваемых), их имена и зарплату.
  8. Найди сотрудников, у которых зарплата больше 100 000 или которые работают в Казани, и при этом получают премию.
🧐 Ответы для самопроверки
-- 1
SELECT name, department, salary
FROM employees;

-- 2
SELECT DISTINCT department
FROM employees;

-- 3
SELECT name, salary
FROM employees
WHERE city = 'Москва' AND salary > 85000;
-- Анна, Павел

-- 4
SELECT name, department
FROM employees
WHERE department IN ('IT', 'Маркетинг');

-- 5
SELECT name, salary
FROM employees
WHERE salary BETWEEN 75000 AND 90000;
-- Иван, Елена, Дарья, Сергей

-- 6
SELECT name
FROM employees
WHERE bonus IS NULL;

-- 7
SELECT name, salary
FROM employees
ORDER BY salary ASC
LIMIT 3;
-- Андрей 70000, Дарья 75000, Иван 80000

-- 8
SELECT name, salary, bonus
FROM employees
WHERE (salary > 100000 OR city = 'Казань')
  AND bonus IS NOT NULL;
-- Анна, Мария

Mini-чеклист, что этап освоен

Ты готова ко второму этапу, если можешь без подсказки объяснить:

  • чем WHERE отличается от ORDER BY по моменту выполнения;
  • почему bonus = NULL не работает;
  • чем LIKE '%а%' отличается от LIKE '_а%';
  • зачем LIMIT нужна парочка с ORDER BY;
  • как скобки меняют результат запроса с AND и OR.

Хочешь, я дам тебе ещё 5 задач с чуть более хитными условиями (на OR, NOT IN и LIKE), а ты пришлёшь свои запросы — я проверю и разберу ошибки?