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
WHERE
created_at >= '2026-01-01' AND created_at < '2027-01-01'
AND country = 'россия'
AND country IN ('россия', 'Россия', 'РОССИЯ')
AND age > 25;
Исправлено: выдача колонок "все" заменено на "определенные", логика в where с числами переработана, соответствие определенному году переработано и убрал функцию LOWER.
+1 -2
View File
@@ -69,8 +69,7 @@ WHERE id = 1;
--Думаю, потому что также используется функция LOWER внутри WHERE
4. Как исправить запрос, чтобы индекс заработал?
CREATE INDEX idx_email ON users(email);
--я добавил индекс, но все равно EXPLAIN ANALYZE показывается Seq Scan. В чем проблема?
CREATE INDEX idx_email ON users(LOWER(email))
----------
--Задача 7 — Функции убивают индексы
+4 -3
View File
@@ -262,7 +262,7 @@
**❓ Вопросы:**
1. Когда выполняется подзапрос в `SELECT`?
В самом начале.
Подзапрос в SELECT вычисляется после того, как отработали секции FROM и WHERE
2. Можно ли использовать алиас `orders_count` в `WHERE`?
Нет, потому что WHERE не видит алиасы
@@ -270,14 +270,15 @@
3. Можно ли использовать его в `ORDER BY`?
Да, потому что order by выполняется после SELECT
4. Перепиши этот запрос через `JOIN`. Какой вариант быстрее? Проверь с `EXPLAIN ANALYZE`! 0.065-0.15
4. Перепиши этот запрос через `JOIN`. Какой вариант быстрее? Проверь с `EXPLAIN ANALYZE`!
SELECT
u.name,
u.age,
COUNT(o.id) AS orders_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.country = 'Россия'
GROUP BY u.name, u.age
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
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 pe.user_id) AS enrolled_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 pe.user_id) * 100.0 / COUNT(DISTINCT pu.id), 2) || '%' AS retention_rate,
ROUND(AVG((SELECT COUNT(pe.id)
FROM pet_enrollments pe)) / COUNT(DISTINCT pu.id), 2) AS avg_courses_per_user,
(SELECT
ROUND(COUNT(DISTINCT plv.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,
(
SELECT
ROUND(AVG(table_first_viewed_at.first_viewed_at::date - pu2.registration_date::date), 2)
FROM pet_users pu2
LEFT JOIN (
JOIN (
SELECT
plv2.user_id,
MIN(plv2.viewed_at) AS first_viewed_at
FROM pet_lesson_views plv2
GROUP BY plv2.user_id
) AS table_first_viewed_at
ON pu2.id = table_first_viewed_at.user_id
) AS table_first_viewed_at ON pu2.id = table_first_viewed_at.user_id
WHERE DATE_TRUNC('month', pu2.registration_date) = pu.cohort_month
) AS avg_time_to_first_view
@@ -31,7 +27,7 @@ FROM (
*,
DATE_TRUNC('month', registration_date) AS cohort_month
FROM pet_users
) AS pu
) AS pu
LEFT JOIN pet_enrollments pe ON pu.id = pe.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;
+10 -10
View File
@@ -1,24 +1,24 @@
-- 1. Задание 1: Анализ drop-off точек
-- Используя conversion_funnel, найди курсы с самым большим процентом отвала между этапами enrolled → started (WHERE stage_name IN (...))
WITH
drop_off
AS
(
WITH drop_off AS (
SELECT
course_id,
stage_name,
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
)
WHERE stage_name IN ('enrolled', 'started')
)
SELECT
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
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% соответственно).
+2 -1
View File
@@ -199,4 +199,5 @@
**Ответ — текстом:**
В чём выгода индекса и где он не поможет
Индекс помогает искать данные быстрее (индекс это как содержание в книге). Индекс не поможет в тех столбцах, где все данные в столбце различаются, например email.
Индекс помогает искать данные быстрее (индекс это как содержание в книге) за счет плана в виде дерева.
Индекс не поможет в тех столбцах, где уникальность данных мала, а также где есть сортировка по знакам >, < или поиск по части строки = "%abc".
+1 -1
View File
@@ -30,7 +30,7 @@
- по дням.
2. Для каждого варианта напиши:
- примерно сколько будет партиций за 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,
name VARCHAR(100) NOT NULL,
age INT,
@@ -8,7 +9,8 @@ CREATE TABLE users (
created_at TIMESTAMPTZ NOT NULL
);
CREATE TABLE products (
CREATE TABLE products
(
id INT PRIMARY KEY NOT NULL,
name VARCHAR(100) NOT NULL,
category VARCHAR(50),
@@ -16,15 +18,17 @@ CREATE TABLE products (
in_stock BOOLEAN
);
CREATE TABLE orders (
id INT PRIMARY KEY NOT NULL,
CREATE TABLE orders
(
id SERIAL PRIMARY KEY NOT NULL,
user_id INT,
order_date TIMESTAMPTZ NOT NULL,
status VARCHAR(20),
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE TABLE order_items (
CREATE TABLE order_items
(
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,