- **Задача 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