Модуль 4 · SQL

SQL: достать данные из базы

Навык №1 в любой вакансии аналитика. Язык, которым «спрашивают» базу данных. Разбираю медленно, по одному слову — так, чтобы понимать, а не заучивать.

🗂 Как это представить: база — это книга с листами Excel Одна таблица — это один лист Excel: строки и столбцы. В нашей учебной базе два листа: clients (клиенты) и deposits (вклады). SQL — это способ задавать листам вопросы: «покажи вот эти столбцы, только такие строки, отсортируй так». Ответ всегда приходит в виде новой таблички.

Запрос собирается из «комнат» — всегда в одном порядке

У любого запроса есть строгий каркас. Каждая строка-«комната» отвечает за своё, и идут они всегда в этом порядке:

SELECT   столбцы            — ЧТО показать (или * — все столбцы)
FROM     таблица            — ОТКУДА, главный лист
JOIN     лист2 ON правило  — приклеить второй лист и ПО КАКОМУ правилу
WHERE    условие            — КАКИЕ строки оставить (фильтр)
ORDER BY столбец            — КАК отсортировать

Обязательны только SELECT и FROM — «что» и «откуда». Остальное добавляют по надобности. Регистр букв не важен: SELECT = select. А вот имена столбцов и таблиц — буква в букву.

Учебная база

Два листа. Столбец client_id во вкладах указывает на id клиента — это ключ, ниточка между листами. Один клиент может иметь много вкладов.

erDiagram
  clients ||--o{ deposits : "имеет вклады"
  clients {
    int id
    text name "имя"
    text city "город"
    int age "возраст"
  }
  deposits {
    int id
    int client_id "чей вклад (ключ)"
    text product "продукт"
    int amount "сумма"
    real rate "ставка %"
    int months "срок"
  }
Один клиент — много вкладов. Значок «многие» (o{) со стороны deposits.

SELECT … FROM — что и откуда

SELECT name, city FROM clients

«Покажи столбцы name и city из листа clients». Звёздочка * — «все столбцы сразу».

🚫 Грабли: пропущенная запятая Столбцы в SELECT разделяются запятой. Если её забыть — SELECT name city — SQL поймёт второе слово как псевдоним (другое имя) для первого, и покажет name под заголовком city. Один пропущенный символ — и данные подписаны неверно.

WHERE — фильтр строк

SELECT * FROM clients WHERE age > 30

Оставит только строки, где условие истинно. Операторы сравнения:

ОператорЗначениеПример
=равноcity = 'Москва'
> <больше / меньше (строго)age > 30
>= <=больше/меньше или равноrate >= 12
!=не равноproduct != 'Вклад'
🚫 Грабли: строго или нет age > 30 НЕ включает ровно 30. Чтобы «30 и старше» — нужно age >= 30. Одна чёрточка меняет ответ.
Текст в условии — всегда в одинарных кавычках: 'Москва'. Число — без кавычек.

ORDER BY — сортировка

SELECT * FROM deposits WHERE rate > 12 ORDER BY amount DESC

DESC — по убыванию (от большего к меньшему), ASC — по возрастанию (по умолчанию, можно не писать). После ORDER BY обязательно назвать столбец — иначе SQL скажет, что запрос не дописан.

JOIN — склеить два листа по ключу

Во вкладах есть только client_id (номер), а имя лежит в другом листе — clients. JOIN подтягивает имя к каждому вкладу, склеивая листы по правилу.

SELECT clients.name, deposits.product, deposits.amount
FROM deposits
JOIN clients ON deposits.client_id = clients.id
  • JOIN clients — присоединить второй лист;
  • ON deposits.client_id = clients.idправило склейки: строку вклада клеим к строке клиента там, где номер клиента во вкладе = id клиента;
  • лист.столбец — уточняем, из какого листа берём столбец (порядок важен: deposits.amount, а не наоборот).
📌 Зачем нужно ON: декартово произведение Без ON SQL склеил бы каждую строку одного листа с каждой строкой другого: 8 клиентов × 12 вкладов = 96 строк-бессмыслиц. ON — это правило, которое из этих 96 оставляет только осмысленные пары (где id совпадает). Отсюда и ровно 12 строк — по одной на вклад.

LEFT JOIN и NULL — сохранить всех, найти «кого нет»

Обычный JOIN выкидывает строки без пары. Клиент без вкладов в него не попадёт вовсе. LEFT JOIN оставляет все строки из левого листа (того, что стоит до LEFT JOIN), а пустые места справа заполняет NULL.

SELECT clients.name, deposits.product, deposits.amount
FROM clients
LEFT JOIN deposits ON clients.id = deposits.client_id

Вернёт всех 8 клиентов. У кого вклада нет — в product и amount будет NULL.

💡 NULL — это «дырка», а не ноль NULL значит «значения нет вообще». Это не 0 и не пустая строка — это отсутствие. Поэтому сравнивать через = нельзя: WHERE amount = NULL молча вернёт «неправда» и покажет пустоту. Для дырок — особый оператор: IS NULL (пусто) и IS NOT NULL (не пусто).

Практическая задача продажника — «кто не оформил ни одного продукта» (спящие клиенты для обзвона):

SELECT clients.id, clients.name
FROM clients
LEFT JOIN deposits ON clients.id = deposits.client_id
WHERE deposits.amount IS NULL
📌 Из какого листа брать столбец У клиента без вкладов весь правый лист — сплошная дырка, поэтому deposits.client_id тоже NULL. Чтобы увидеть настоящий номер, берём clients.id — из левого, реального листа. Всегда осознавай, из какого листа тянешь столбец: одни и те же данные из левого и правого могут отличаться.

Ключевые слова

SELECT … FROM — что и откуда WHERE — фильтр строк ORDER BY … DESC/ASC — сортировка JOIN … ON — склейка по ключу LEFT JOIN — сохранить все левые строки NULL — дырка (IS NULL / IS NOT NULL) > строго, >= с равенством
🎯 Проверь себя на базе банк.db (без подсказок) 1. Все вклады продукта «Вклад» с суммой больше 100000, по убыванию суммы.
2. Имя клиента и сумма для каждого вклада (JOIN … ON).
3. Клиенты из Москвы старше 30.
4. Кто из клиентов без вкладов (LEFT JOIN + IS NULL), с их настоящим id.