За этот разбор вы отберёте заказы, посчитаете сумму покупок и найдёте ошибку в соединении таблиц. Чтение займёт около 9 минут. На выполнение заданий заложите ещё от 20 до 40 минут.
01 / Навыки и практика
Что понадобится и чему вы научитесь
Материал подойдёт начинающим тестировщикам, аналитикам и разработчикам. Достаточно понимать, что таблица состоит из строк и столбцов. Мы используем SQLite и вымышленные данные магазина. Рабочую базу и сведения клиентов подключать не нужно.
Можно заниматься прямо здесь: откройте тренажёр, выберите задачу и напишите SELECT-запрос. Учебные таблицы уже подготовлены. Если предпочитаете свой редактор SQLite, создайте пустую базу и выполните код из раздела с данными.
Сначала прочитайте условие, затем набросайте запрос. Если застряли, откройте одну подсказку. Ответ смотрите после своей попытки. Нейросеть здесь необязательна: данные, подсказки и решения уже есть в статье.
Результат занятия конкретный: вы можете объяснить, какие строки выбирает запрос и почему. Это первая практика SQL, а не полный курс языка.
02 / Навыки и практика
Подготовьте две учебные таблицы
customers содержит покупателей. orders содержит заказы: customer_id указывает на customers.id, amount хранит сумму в целых учебных единицах, status принимает значения paid (оплачен) и cancelled (отменён). В реальном проекте правила учёта оплат и возвратов могут отличаться.
| id покупателя | Имя |
|---|---|
| 1 | Анна |
| 2 | Борис |
| 3 | Вера |
| 4 | Глеб |
| id заказа | customer_id | amount | status |
|---|---|---|---|
| 101 | 1 | 1200 | paid |
| 102 | 1 | 500 | cancelled |
| 103 | 1 | 800 | paid |
| 104 | 2 | 1500 | paid |
| 105 | 3 | 700 | cancelled |
У Анны два оплаченных заказа и один отменённый. У Веры есть только отменённый заказ, у Глеба заказов нет. Эти различия помогут проверить, не теряет ли запрос покупателей.
Код для создания таблиц: выполнить один раз
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
amount INTEGER NOT NULL,
status TEXT NOT NULL,
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
INSERT INTO customers VALUES
(1, 'Анна'), (2, 'Борис'),
(3, 'Вера'), (4, 'Глеб');
INSERT INTO orders VALUES
(101, 1, 1200, 'paid'),
(102, 1, 500, 'cancelled'),
(103, 1, 800, 'paid'),
(104, 2, 1500, 'paid'),
(105, 3, 700, 'cancelled');После выполнения проверьте данные: SELECT * FROM customers; должен вернуть четыре строки, SELECT * FROM orders; пять. Ошибка table already exists означает, что таблица с таким именем уже есть. Откройте новую пустую учебную базу; не удаляйте незнакомые таблицы.
03 / Навыки и практика
Попробуйте SQL прямо в статье
Выберите задачу. Таблицы customers(id, name) и orders(id, customer_id, amount, status) уже содержат данные из предыдущего раздела. Ничего устанавливать или регистрировать не нужно.
Если пока не знаете, что написать, перейдите к первой задаче с подсказками. Сначала попробуйте сами, потом откройте решение.
04 / Навыки и практика
Настройте нейросеть на подсказки
Вставьте в выбранный чат следующий запрос, а после него код создания таблиц. Для каждой задачи добавляйте её условие и свою попытку. Не просите просто «решить задание».
Я изучаю SQL на SQLite. Ниже схема и вымышленные данные.
Работай как наставник:
1. Не выдавай готовый запрос до моей попытки.
2. Если я застрял, дай одну подсказку без решения и дождись ответа.
3. После моей попытки проверь логику и предложи контрпример.
4. Не меняй таблицы, данные и условие задачи.
5. Различай предполагаемый результат и результат реального запуска.
6. После исправления попроси меня объяснить решение своими словами.
Если запрос верен, не придумывай ошибку ради критики. Инструкция не гарантирует, что модель будет её соблюдать. Если она сразу прислала ответ, не переписывайте его. Закройте ответ и попробуйте решить задачу по условию. Если модель пишет «проверено», попросите уточнить, запускала ли она SQL: убедительное объяснение само по себе не является проверкой.
05 / Навыки и практика
Задача 1. Найдите оплаченные заказы от 1000
Условие. Выведите id и amount оплаченных заказов на сумму не меньше 1000. Отсортируйте строки по id по возрастанию.
Перед написанием запроса ответьте себе: должен ли попасть заказ ровно на 1000? Да. Должен ли попасть отменённый заказ на 2000? Нет. Так вы заранее определяете границы условия.
Подсказка 1
Нужна только таблица orders. Сначала выберите два нужных столбца через SELECT, затем укажите таблицу через FROM.
Подсказка 2
В WHERE соедините проверку статуса и суммы оператором AND. «Не меньше» означает >=. Текстовый статус заключите в одинарные кавычки.
Проверить результат и решение
SELECT id, amount
FROM orders
WHERE status = 'paid' AND amount >= 1000
ORDER BY id;| id | amount |
|---|---|
| 101 | 1200 |
| 104 | 1500 |
WHERE оставляет подходящие строки, ORDER BY задаёт порядок. Заказ 103 оплачен, но его сумма меньше порога. Заказ 102 отменён, поэтому не подходит.
Ловушка: замена AND на OR меняет смысл. Тогда достаточно выполнить одно из условий, и оплаченный заказ на 800 тоже попадёт в результат.
06 / Навыки и практика
Задача 2. Посчитайте сумму оплаченных заказов
Условие. Для каждого покупателя с оплаченными заказами выведите customer_id и общую сумму paid_total. Отменённые заказы не учитывайте. Порядок строк: по customer_id.
Сначала посчитайте вручную: у Анны 1200 + 800 = 2000, у Бориса 1500. Ожидаются две строки. Это маленькая независимая проверка, с которой можно сравнить ответ модели.
Подсказка 1
Отберите оплаченные заказы до подсчёта. В этом упражнении покупатели без оплат не нужны, поэтому достаточно одной таблицы orders.
Подсказка 2
GROUP BY customer_id объединит заказы одного покупателя в группу. SUM(amount) сложит суммы внутри каждой группы, а AS paid_total задаст имя столбцу результата.
Проверить результат и решение
SELECT customer_id, SUM(amount) AS paid_total
FROM orders
WHERE status = 'paid'
GROUP BY customer_id
ORDER BY customer_id;| customer_id | paid_total |
|---|---|
| 1 | 2000 |
| 2 | 1500 |
Если у Анны получилось 2500, вы включили отменённый заказ. Если вместо двух строк одна сумма 3500, проверьте группировку.
Не считайте покупателей по количеству заказов: у одного человека их несколько. И не объединяйте людей по имени, когда у вас есть уникальный id: двух разных Анн нельзя превращать в одного покупателя.
07 / Навыки и практика
Задача 3. Сохраните покупателей без оплат
Условие. Выведите всех четырёх покупателей: id, name, количество оплаченных заказов paid_count и их сумму paid_total. При отсутствии оплат должны стоять нули. Отсортируйте по id.
Это главное усложнение: покупатель без заказов и покупатель только с отменёнными заказами тоже должны остаться в отчёте.
Подсказка 1
Начните с customers и присоедините заказы через LEFT JOIN. Покупатели из левой таблицы сохранятся, даже если подходящего заказа справа нет.
Подсказка 2
Условие o.status = 'paid' добавьте в ON вместе со связью по покупателю. Считайте COUNT(o.id), а не COUNT(*). Для суммы без подходящих заказов используйте COALESCE(SUM(o.amount), 0).
Проверить результат и решение
SELECT c.id, c.name,
COUNT(o.id) AS paid_count,
COALESCE(SUM(o.amount), 0) AS paid_total
FROM customers AS c
LEFT JOIN orders AS o
ON o.customer_id = c.id AND o.status = 'paid'
GROUP BY c.id, c.name
ORDER BY c.id;| id | name | paid_count | paid_total |
|---|---|---|---|
| 1 | Анна | 2 | 2000 |
| 2 | Борис | 1 | 1500 |
| 3 | Вера | 0 | 0 |
| 4 | Глеб | 0 | 0 |
c и o являются короткими именами таблиц. ON определяет, какие заказы присоединять. Если подходящих нет, в полях заказа появляется NULL, то есть отсутствие значения.
COUNT(o.id) учитывает только ненулевые значения идентификатора. COUNT(*) считает и сохранённую строку покупателя без заказа, поэтому дал бы ему единицу. SUM без ненулевых входных значений возвращает NULL; COALESCE заменяет его нулём.
Проверяйте не только сумму 3500, но и состав строк. Отчёт может показывать правильную общую сумму и при этом скрывать часть покупателей.
08 / Навыки и практика
Ошибка, которую красивое объяснение не исправит
Вот специально составленный ошибочный вариант третьей задачи. Он запускается без синтаксической ошибки:
SELECT c.id, c.name, COUNT(o.id) AS paid_count,
COALESCE(SUM(o.amount), 0) AS paid_total
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
WHERE o.status = 'paid'
GROUP BY c.id, c.name
ORDER BY c.id; Условие статуса перенесено в WHERE. Вера отсекается, потому что её заказ отменён. Глеб отсекается, потому что после соединения у него NULL в поле статуса, и проверка равенства 'paid' не даёт истину. Останутся только Анна и Борис.
Добавить в WHERE условие OR o.id IS NULL тоже недостаточно: Глеб вернётся, но Вера с существующим отменённым заказом всё ещё пропадёт. Для данного условия фильтр оплаченных заказов нужен в ON, как в проверенном решении.
Если нейросеть предлагает исправление, попросите показать результат для каждого покупателя. Затем запустите запрос сами. Мы выполнили решения и этот ошибочный вариант в SQLite: правильный отчёт возвращает четыре строки, ошибочный две.
09 / Навыки и практика
Как понять, что вы научились, а не скопировали
Закройте решения и измените условие: теперь нужны все покупатели, количество и сумма только отменённых заказов. До запуска предскажите результат: Анна 1 и 500, Борис 0 и 0, Вера 1 и 700, Глеб 0 и 0.
Затем объясните без нейросети три вещи: зачем нужен LEFT JOIN, почему фильтр стоит в ON и чем отличаются COUNT(*) и COUNT(o.id). Если объяснение не получается, вернитесь к конкретной строке Веры или Глеба.
Для следующего занятия попросите нейросеть дать похожую задачу с другим сюжетом, но теми же операциями. Пример запроса:
Дай одну новую задачу на LEFT JOIN и GROUP BY в SQLite.
Используй две небольшие таблицы и вымышленные данные.
Обязательно включи человека без связанных записей
и человека только с записями, не проходящими фильтр.
Покажи данные и условие, но пока не показывай решение.
После моей попытки попроси предсказать результат по строкам. Новые данные тоже проверьте вручную. Главный признак прогресса: вы заранее понимаете, кто должен остаться в результате, и можете найти причину расхождения. Количество полученных от нейросети запросов этого не показывает.
Вопросы по теме
Что ещё стоит уточнить
Можно ли обойтись без платной нейросети?
Да. Все задания, данные, подсказки и решения есть в статье. Для проверки нужен редактор SQLite. Чат лишь помогает разобрать вашу конкретную попытку.
Почему ответ нейросети отличается от решения?
Корректных запросов может быть несколько. Сравните результат, условия отбора, строки без заказов и поведение на новых данных. Совпадение на одном наборе ещё не доказывает общую правильность.
Можно ли выполнять код в рабочей базе?
Для этого занятия создайте отдельную пустую учебную базу. Подготовительный код создаёт таблицы и добавляет строки. Схемы, доступы и данные работодателя в чат не отправляйте.
Продолжим в Telegram
Практика SQL стала понятнее?
Сохраните статью для следующего занятия. А познакомиться со школой, профессиями и карьерными шагами можно в канале «АйТи с 0 | IT NOMAD».
Перейти в Telegram-канал