fix mistakes

This commit is contained in:
Dmitry Medvedev
2026-08-01 22:07:18 +05:00
parent 1f770a0413
commit 4f56e71ef8
8 changed files with 45 additions and 43 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ SELECT id, name, age
FROM users FROM users
WHERE WHERE
created_at >= '2026-01-01' AND created_at < '2027-01-01' created_at >= '2026-01-01' AND created_at < '2027-01-01'
AND country = 'россия' AND country IN ('россия', 'Россия', 'РОССИЯ')
AND age > 25; AND age > 25;
Исправлено: выдача колонок "все" заменено на "определенные", логика в where с числами переработана, соответствие определенному году переработано и убрал функцию LOWER. Исправлено: выдача колонок "все" заменено на "определенные", логика в where с числами переработана, соответствие определенному году переработано и убрал функцию LOWER.
+1 -2
View File
@@ -69,8 +69,7 @@ WHERE id = 1;
--Думаю, потому что также используется функция LOWER внутри WHERE --Думаю, потому что также используется функция LOWER внутри WHERE
4. Как исправить запрос, чтобы индекс заработал? 4. Как исправить запрос, чтобы индекс заработал?
CREATE INDEX idx_email ON users(email); CREATE INDEX idx_email ON users(LOWER(email))
--я добавил индекс, но все равно EXPLAIN ANALYZE показывается Seq Scan. В чем проблема?
---------- ----------
--Задача 7 — Функции убивают индексы --Задача 7 — Функции убивают индексы
+4 -3
View File
@@ -262,7 +262,7 @@
**❓ Вопросы:** **❓ Вопросы:**
1. Когда выполняется подзапрос в `SELECT`? 1. Когда выполняется подзапрос в `SELECT`?
В самом начале. Подзапрос в SELECT вычисляется после того, как отработали секции FROM и WHERE
2. Можно ли использовать алиас `orders_count` в `WHERE`? 2. Можно ли использовать алиас `orders_count` в `WHERE`?
Нет, потому что WHERE не видит алиасы Нет, потому что WHERE не видит алиасы
@@ -270,14 +270,15 @@
3. Можно ли использовать его в `ORDER BY`? 3. Можно ли использовать его в `ORDER BY`?
Да, потому что order by выполняется после SELECT Да, потому что order by выполняется после SELECT
4. Перепиши этот запрос через `JOIN`. Какой вариант быстрее? Проверь с `EXPLAIN ANALYZE`! 0.065-0.15 4. Перепиши этот запрос через `JOIN`. Какой вариант быстрее? Проверь с `EXPLAIN ANALYZE`!
SELECT SELECT
u.name, u.name,
u.age, u.age,
COUNT(o.id) AS orders_count COUNT(o.id) AS orders_count
FROM users u FROM users u
LEFT JOIN orders o ON o.user_id = u.id LEFT JOIN orders o ON o.user_id = u.id
WHERE u.country = 'Россия'
GROUP BY u.name, u.age GROUP BY u.name, u.age
ORDER BY orders_count DESC; ORDER BY orders_count DESC;
Второй запрос через JOIN выполняется дольше (0.06 и 0.08 мс соответственно) Второй запрос через JOIN выполняется быстрее (0.13 и 0.1 мс соответственно)
+9 -12
View File
@@ -2,27 +2,23 @@ CREATE MATERIALIZED
VIEW user_cohort_analysis AS VIEW user_cohort_analysis AS
SELECT SELECT
TO_CHAR(pu.cohort_month, 'YYYY-MM') AS MONTH, TO_CHAR(pu.cohort_month, 'YYYY-MM') AS month,
COUNT(DISTINCT pu.id) AS users_in_cohort, COUNT(DISTINCT pu.id) AS users_in_cohort,
COUNT(DISTINCT pe.user_id) AS enrolled_users, COUNT(DISTINCT pe.user_id) AS enrolled_users,
COUNT(DISTINCT plv.user_id) AS active_users, COUNT(DISTINCT plv.user_id) AS active_users,
--ROUND(COUNT(DISTINCT plv.user_id) * 100.0 / COUNT(DISTINCT pu.id), 2) || '%' AS retention_rate, ROUND(COUNT(DISTINCT plv.user_id) * 100.0 / COUNT(DISTINCT pu.id), 2) || '%' AS retention_rate,
ROUND(COUNT(DISTINCT pe.user_id) * 100.0 / COUNT(DISTINCT pu.id), 2) || '%' AS retention_rate, ROUND(COUNT(DISTINCT pe.id) * 1.0 / COUNT(DISTINCT pu.id), 2) AS avg_courses_per_user,
ROUND(AVG((SELECT COUNT(pe.id) (
FROM pet_enrollments pe)) / COUNT(DISTINCT pu.id), 2) AS avg_courses_per_user, SELECT
(SELECT
ROUND(AVG(table_first_viewed_at.first_viewed_at::date - pu2.registration_date::date), 2) ROUND(AVG(table_first_viewed_at.first_viewed_at::date - pu2.registration_date::date), 2)
FROM pet_users pu2 FROM pet_users pu2
LEFT JOIN ( JOIN (
SELECT SELECT
plv2.user_id, plv2.user_id,
MIN(plv2.viewed_at) AS first_viewed_at MIN(plv2.viewed_at) AS first_viewed_at
FROM pet_lesson_views plv2 FROM pet_lesson_views plv2
GROUP BY plv2.user_id GROUP BY plv2.user_id
) AS table_first_viewed_at ) AS table_first_viewed_at ON pu2.id = table_first_viewed_at.user_id
ON pu2.id = table_first_viewed_at.user_id
WHERE DATE_TRUNC('month', pu2.registration_date) = pu.cohort_month WHERE DATE_TRUNC('month', pu2.registration_date) = pu.cohort_month
) AS avg_time_to_first_view ) AS avg_time_to_first_view
@@ -31,7 +27,7 @@ FROM (
*, *,
DATE_TRUNC('month', registration_date) AS cohort_month DATE_TRUNC('month', registration_date) AS cohort_month
FROM pet_users FROM pet_users
) AS pu ) AS pu
LEFT JOIN pet_enrollments pe ON pu.id = pe.user_id LEFT JOIN pet_enrollments pe ON pu.id = pe.user_id
LEFT JOIN pet_lesson_views plv ON pu.id = plv.user_id LEFT JOIN pet_lesson_views plv ON pu.id = plv.user_id
@@ -39,3 +35,4 @@ GROUP BY pu.cohort_month
ORDER BY pu.cohort_month; ORDER BY pu.cohort_month;
+10 -10
View File
@@ -1,24 +1,24 @@
-- 1. Задание 1: Анализ drop-off точек -- 1. Задание 1: Анализ drop-off точек
-- Используя conversion_funnel, найди курсы с самым большим процентом отвала между этапами enrolled → started (WHERE stage_name IN (...)) -- Используя conversion_funnel, найди курсы с самым большим процентом отвала между этапами enrolled → started (WHERE stage_name IN (...))
WITH WITH drop_off AS (
drop_off
AS
(
SELECT SELECT
course_id, course_id,
stage_name, stage_name,
users_count, users_count,
LAG(users_count) OVER (PARTITION BY course_id) AS prev LAG(users_count) OVER (
PARTITION BY course_id
ORDER BY stage_name
) AS prev
FROM conversion_funnel FROM conversion_funnel
) WHERE stage_name IN ('enrolled', 'started')
)
SELECT SELECT
course_id, course_id,
ROUND(1 - users_count * 1.0 / NULLIF(prev, 0), 2) * 100 || '%' AS percent_of_drop ROUND((1 - users_count * 1.0 / NULLIF(prev, 0)) * 100, 2) || '%' AS percent_of_drop
FROM drop_off FROM drop_off
WHERE stage_name = 'started' WHERE stage_name = 'started'
ORDER BY percent_of_drop DESC ORDER BY (1 - users_count * 1.0 / NULLIF(prev, 0)) DESC;
-- ОТВЕТ: Самые большие проценты отвала между enrolled и started замечены на курсе 1 и 3 (62 и 67% соответственно). -- ОТВЕТ: Самые большие проценты отвала между enrolled и started замечены на курсе 1 и 3 (62 и 67% соответственно).
+2 -1
View File
@@ -199,4 +199,5 @@
**Ответ — текстом:** **Ответ — текстом:**
В чём выгода индекса и где он не поможет В чём выгода индекса и где он не поможет
Индекс помогает искать данные быстрее (индекс это как содержание в книге). Индекс не поможет в тех столбцах, где все данные в столбце различаются, например email. Индекс помогает искать данные быстрее (индекс это как содержание в книге) за счет плана в виде дерева.
Индекс не поможет в тех столбцах, где уникальность данных мала, а также где есть сортировка по знакам >, < или поиск по части строки = "%abc".
+1 -1
View File
@@ -30,7 +30,7 @@
- по дням. - по дням.
2. Для каждого варианта напиши: 2. Для каждого варианта напиши:
- примерно сколько будет партиций за 10 лет; - примерно сколько будет партиций за 10 лет;
по годам - 10 * 1 = 10, по месяцам - 10 * 12 = 120, по дням 366 * 2 + 365 * 4 = 2652. по годам - 10 * 1 = 10, по месяцам - 10 * 12 = 120, по дням 366 * 2 + 365 * 8 = 3652.
- плюсы и минусы (удаление старых данных, поддержка, скорость запросов). - плюсы и минусы (удаление старых данных, поддержка, скорость запросов).
+9 -5
View File
@@ -1,4 +1,5 @@
CREATE TABLE users ( CREATE TABLE users
(
id INT PRIMARY KEY NOT NULL, id INT PRIMARY KEY NOT NULL,
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
age INT, age INT,
@@ -8,7 +9,8 @@ CREATE TABLE users (
created_at TIMESTAMPTZ NOT NULL created_at TIMESTAMPTZ NOT NULL
); );
CREATE TABLE products ( CREATE TABLE products
(
id INT PRIMARY KEY NOT NULL, id INT PRIMARY KEY NOT NULL,
name VARCHAR(100) NOT NULL, name VARCHAR(100) NOT NULL,
category VARCHAR(50), category VARCHAR(50),
@@ -16,15 +18,17 @@ CREATE TABLE products (
in_stock BOOLEAN in_stock BOOLEAN
); );
CREATE TABLE orders ( CREATE TABLE orders
id INT PRIMARY KEY NOT NULL, (
id SERIAL PRIMARY KEY NOT NULL,
user_id INT, user_id INT,
order_date TIMESTAMPTZ NOT NULL, order_date TIMESTAMPTZ NOT NULL,
status VARCHAR(20), status VARCHAR(20),
FOREIGN KEY (user_id) REFERENCES users(id) FOREIGN KEY (user_id) REFERENCES users(id)
); );
CREATE TABLE order_items ( CREATE TABLE order_items
(
order_id INT NOT NULL, order_id INT NOT NULL,
product_id INT NOT NULL, product_id INT NOT NULL,
quantity INT NOT NULL, quantity INT NOT NULL,