fix mistakes
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 — Функции убивают индексы
|
||||
|
||||
@@ -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 мс соответственно)
|
||||
@@ -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
|
||||
|
||||
@@ -39,3 +35,4 @@ GROUP BY pu.cohort_month
|
||||
ORDER BY pu.cohort_month;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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% соответственно).
|
||||
|
||||
|
||||
@@ -199,4 +199,5 @@
|
||||
**Ответ — текстом:**
|
||||
В чём выгода индекса и где он не поможет
|
||||
|
||||
Индекс помогает искать данные быстрее (индекс это как содержание в книге). Индекс не поможет в тех столбцах, где все данные в столбце различаются, например email.
|
||||
Индекс помогает искать данные быстрее (индекс это как содержание в книге) за счет плана в виде дерева.
|
||||
Индекс не поможет в тех столбцах, где уникальность данных мала, а также где есть сортировка по знакам >, < или поиск по части строки = "%abc".
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user