added explain and poryadok sql
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
- **Задача 1** — Запрос с группировкой
|
||||
|
||||
SELECT country, COUNT(*) AS users_count
|
||||
FROM users
|
||||
WHERE is_active = true
|
||||
GROUP BY country
|
||||
HAVING COUNT(*) > 1
|
||||
ORDER BY users_count DESC;
|
||||
|
||||
**❓ Вопросы:**
|
||||
|
||||
1. Когда применится `WHERE` — до или после `GROUP BY`?
|
||||
До группировки, потому что это фильтрация строк
|
||||
2. Когда применится `HAVING` — до или после `GROUP BY`?
|
||||
После группировки, потому что это фильтрация групп
|
||||
3. Можно ли использовать алиас `users_count` в `HAVING`?
|
||||
Нельзя, тк HAVING применяется до SELECT
|
||||
4. Можно ли использовать алиас `users_count` в `ORDER BY`?
|
||||
Можно, тк ORDER BY применяется после SELECT
|
||||
|
||||
|
||||
- **Задача 2** — JOIN с фильтрацией
|
||||
|
||||
SELECT u.name, o.order_date, o.status
|
||||
FROM users u
|
||||
JOIN orders o ON u.id = o.user_id
|
||||
WHERE u.country = 'Россия' AND o.status = 'completed'
|
||||
ORDER BY o.order_date DESC;
|
||||
|
||||
**✅ Задание:**
|
||||
|
||||
- Опиши порядок выполнения своими словами (как будто объясняешь другу-новичку).
|
||||
На самом первом этапе идет формирование таблицы данных из фром и джойна, далее данные отфильтровываются в WHERE и выполняется вычисление выражение черезе SELECT, в конечном счете строки фильруются по order_date через ORDER BY
|
||||
|
||||
- **Задача 3** — Найди ошибку
|
||||
|
||||
Дан запрос:
|
||||
|
||||
SELECT country, AVG(age) AS avg_age
|
||||
FROM users
|
||||
GROUP BY country
|
||||
HAVING country = 'Россия';
|
||||
|
||||
**❓ Вопросы:**
|
||||
|
||||
1. Запрос работает, но написан **неэффективно**. Почему?
|
||||
Потому что фильтрация по "Россия" идет в самом конце запроса, когда можно было на первоначальном этапе сделать через WHERE, чтобы не читать всю таблицу. Плюс можно добавить индекс по столюцу country
|
||||
2. Перепиши его правильно, используя WHERE.
|
||||
SELECT
|
||||
country,
|
||||
AVG(age) AS avg_age
|
||||
FROM users
|
||||
WHERE country = 'RU'
|
||||
GROUP BY country;
|
||||
3. Объясни, почему твой вариант быстрее.
|
||||
Объяснил в 1ом вопросе.
|
||||
|
||||
- **Задача 4** — Исправь запрос
|
||||
|
||||
SELECT category, AVG(price) AS avg_price
|
||||
FROM products
|
||||
GROUP BY category
|
||||
HAVING category = 'Электроника' AND AVG(price) > 20000;
|
||||
|
||||
**✅ Задание:**
|
||||
|
||||
1. Перепиши запрос так, чтобы часть условий была в `WHERE`.
|
||||
SELECT category, AVG(price) AS avg_price
|
||||
FROM products
|
||||
WHERE category = 'Электроника'
|
||||
GROUP BY category
|
||||
HAVING AVG(price) > 20000;
|
||||
2. Объясни, почему это быстрее.
|
||||
Потому что сразу происходит фильтрация строк и дальнейшая группировка и фильтрация уже не затрагивает ненужные строки (чем раньше фильтрация, тем лучше)
|
||||
3. Нарисуй схему: сколько строк будет обработано в каждом случае.
|
||||
Если не исполбзовать WHERE , то ан этапе группировке на входе будет 7 строк , которые далее отфильтуются.
|
||||
А если сразу использовать WHERE, то на входе в группировку будет всего три строки
|
||||
|
||||
- **Задача 5** — Исправь все ошибки
|
||||
|
||||
SELECT
|
||||
country,
|
||||
COUNT(*) AS users_count
|
||||
FROM users
|
||||
WHERE users_count > 1
|
||||
GROUP BY country
|
||||
ORDER BY country;
|
||||
|
||||
**✅ Задание:**
|
||||
|
||||
- Найди ошибку и исправь запрос.
|
||||
|
||||
SELECT
|
||||
country,
|
||||
COUNT(*) AS users_count
|
||||
FROM users
|
||||
--WHERE users_count > 1
|
||||
GROUP BY country
|
||||
HAVING COUNT(*) > 1 --добавлена фильтрация по группам
|
||||
ORDER BY country;
|
||||
- **Задача 6** — Полный цикл выполнения
|
||||
|
||||
SELECT
|
||||
u.country,
|
||||
COUNT(o.id) AS orders_count,
|
||||
AVG(o.id) AS avg_order_id
|
||||
FROM users u
|
||||
LEFT JOIN orders o ON u.id = o.user_id
|
||||
WHERE u.is_active = true
|
||||
GROUP BY u.country
|
||||
HAVING COUNT(o.id) > 1
|
||||
ORDER BY orders_count DESC
|
||||
LIMIT 3;
|
||||
|
||||
**✅ Задание:**
|
||||
|
||||
- Опиши ПОЛНЫЙ порядок выполнения (все 7 шагов) и объясни, что происходит на каждом.
|
||||
1. Формирование таблицы данных из FROM и JOIN
|
||||
2. Фильтрация строк WHERE
|
||||
3. Группировка строк GROUP BY
|
||||
4. Фильтрация групп HAVING
|
||||
5. Вывод столбцов SELECT
|
||||
6. Сортировка ORDER BY
|
||||
7. Лимитирование выхода строк LIMIT
|
||||
|
||||
- **Задача 7** — Оптимизация
|
||||
|
||||
Сравни два запроса:
|
||||
|
||||
-- Запрос А
|
||||
SELECT category, COUNT(*)
|
||||
FROM products
|
||||
GROUP BY category
|
||||
HAVING category = 'Электроника';
|
||||
|
||||
-- Запрос Б
|
||||
SELECT category, COUNT(*)
|
||||
FROM products
|
||||
WHERE category = 'Электроника'
|
||||
GROUP BY category;
|
||||
|
||||
**❓ Вопросы:**
|
||||
|
||||
1. Какой запрос быстрее? Почему?
|
||||
Запрос 2 быстрее потому что на этапе WHERE сразу отфильтровываются ненужные строки.
|
||||
|
||||
2. Нарисуй таблицу: на каком шаге сколько строк обрабатывается в каждом запросе.
|
||||
На этапе FROM всего 7 строк. Далее если смотреть по запросу А они превращаются в 4 строки и на HAVING в 1.
|
||||
Если смотреть на запрос Б, то после FROM остается 3 строки, содержащие данные только о категории 'Электроника', далее они просто группируются в одну.
|
||||
|
||||
3. Выполни оба с `EXPLAIN ANALYZE` и сравни `Execution Time.`
|
||||
Запрос А - 0.04 мс
|
||||
Запрос Б - 0.03 мс
|
||||
|
||||
|
||||
|
||||
- **Задача 8** — Многоэтапная фильтрация
|
||||
|
||||
SELECT
|
||||
u.name,
|
||||
COUNT(o.id) AS orders_count
|
||||
FROM users u
|
||||
LEFT JOIN orders o ON u.id = o.user_id
|
||||
WHERE u.country = 'Россия'
|
||||
AND u.age > 25
|
||||
AND o.status = 'completed'
|
||||
GROUP BY u.name
|
||||
HAVING COUNT(o.id) >= 2
|
||||
ORDER BY orders_count DESC;
|
||||
|
||||
**❓ Вопросы:**
|
||||
|
||||
1. Когда применяются условия `WHERE`?
|
||||
Для фильтрации строк
|
||||
2. Когда применяется условие `HAVING`?
|
||||
Для фильтрации групп
|
||||
3. В чём разница между фильтрацией по `o.status` в `WHERE` и по `COUNT(o.id)` в `HAVING`?
|
||||
В WHERE фильтрация подразумевает выполненные заказы, а в HAVING подразумевает более 2х штук. Соответственно получается, что сначала мы фильтруем выполненные заказы, а потом людей у которых заказов более 2х штук.
|
||||
|
||||
|
||||
- **Задача 9** — JOIN и ORDER BY
|
||||
|
||||
SELECT
|
||||
u.name,
|
||||
p.name AS product_name,
|
||||
p.price
|
||||
FROM users u
|
||||
JOIN orders o ON u.id = o.user_id
|
||||
JOIN order_items oi ON o.id = oi.order_id
|
||||
JOIN products p ON oi.product_id = p.id
|
||||
WHERE u.country = 'Россия'
|
||||
ORDER BY p.price DESC
|
||||
LIMIT 5;
|
||||
|
||||
**❓ Вопросы:**
|
||||
|
||||
1. На каком этапе применяется `ORDER BY`?
|
||||
После FROM, JOIN, WHERE, SELECT и до LIMIT.
|
||||
|
||||
2. Почему `LIMIT` идёт после `ORDER BY`, а не до?
|
||||
В таком случае нарушалась бы логика использования этих двух функций. Например, нужно вывести топ-3 (или топ-3 наименьшие) позиции из списка. И если лимит стоял бы до сортировки, то мы могли бы вывести совсем не топ значения. Данная последовательность помогает сначала сделать сортировка вверх или вниз и потом вывести нужные строки.
|
||||
|
||||
3. Что будет, если поменять их местами (технически невозможно, но подумай концептуально)?
|
||||
В таком случае нарушалась бы логика использования этих двух функций. Например, нужно вывести топ-3 (или топ-3 наименьшие) позиции из списка. И если лимит стоял бы до сортировки, то мы могли бы вывести совсем не топ значения. Данная последовательность помогает сначала сделать сортировка вверх или вниз и потом вывести нужные строки.
|
||||
|
||||
- **Задача 10** — Напиши запрос с нуля
|
||||
|
||||
✅ Тебе нужно получить:
|
||||
|
||||
- Список категорий товаров
|
||||
- Количество товаров в каждой категории
|
||||
- Среднюю цену товаров в категории
|
||||
- Только те категории, где средняя цена > 15000
|
||||
- Только те категории, где товаров >= 2
|
||||
- Отсортировать по средней цене (от большей к меньшей)
|
||||
- Взять только топ-3
|
||||
|
||||
**✅ Задание:**
|
||||
|
||||
1. Напиши запрос
|
||||
|
||||
SELECT
|
||||
p.category AS category,
|
||||
COUNT(*) AS count_product_in_category,
|
||||
AVG(price) AS avg_price_product_in_category
|
||||
FROM products p
|
||||
GROUP BY p.category
|
||||
HAVING AVG(price) > 15000 AND COUNT(*) >= 2
|
||||
ORDER BY avg_price_product_in_category DESC
|
||||
LIMIT 3;
|
||||
|
||||
2. Опиши порядок выполнения
|
||||
1. Формируется таблица из FROM
|
||||
2. Группировка GROUP BY (Так как строки фильтровать не нужно)
|
||||
3. Фильтрация групп HAVING
|
||||
4. Вывод значений SELECT
|
||||
5. Сортировка ORDER BY
|
||||
6. Лимитирование LIMIT
|
||||
|
||||
3. Объясни, почему использовал `WHERE` или `HAVING` для каждого условия
|
||||
Использовал только HAVING потому что по условию нужно фильтровать именно группы, а не строки.
|
||||
|
||||
4. Выполни с `EXPLAIN ANALYZE` и посмотри план
|
||||
1. чтение таблицы products
|
||||
2. Группировка с фильтрацией групп (hash aggregate)
|
||||
3. Сортировка Sort key
|
||||
4. LIMIT
|
||||
Reference in New Issue
Block a user