add tasks with function, string, logic

This commit is contained in:
Dmitry Medvedev
2026-05-31 23:21:45 +05:00
parent 204913caa8
commit d5155bed65
+109
View File
@@ -0,0 +1,109 @@
--task 1
--Задача 1. Давность регистрации пользователей
SELECT name, created_at::date AS created_date, CURRENT_DATE - created_at::date AS date_since_registration
FROM users u
WHERE CURRENT_DATE - created_at::date > 180
ORDER BY date_since_registration DESC
/*Как бы ты использовал такое поле в реальном продукте (что можно делать с очень «старыми» пользователями)?
В зависимости от их активности можно предложить те или иные плюшки.
Почему удобнее сразу вычитать created_at::date, а не created_at как timestamp?
Потому что CURRENT_DATE - это просто текущая дата без учета времени
*/
--task 2
--Задача 2. Нормализация email и доменов
SELECT
name,
LOWER(email) AS email_clean,
substring(LOWER(email) FROM POSITION('@' IN email) +1) AS domain
FROM users
WHERE email IS NOT NULL
ORDER BY domain, name
/*
Зачем в реальных системах приводят email к нижнему регистру и выделяют домен отдельно?
Возможно потому что люди могут писать с разным регистром, и если бы это учитывалось, то одинаковые почтовые ящики с разными регистрами были бы совершенно разными.
А системе не нужны дубликаты с разными регистрами.
Что будет, если по ошибке не отфильтровать email IS NOT NULL (что получишь в domain)?
Получу NULL,человек не заполнил ячейку имэйла при регистрации.
*/
--task 3
--Задача 3. Сегменты по возрасту
SELECT
name,
age,
CASE
WHEN age < 25 THEN 'young'
WHEN age BETWEEN 25 and 35 THEN 'adult'
WHEN age > 35 THEN 'senior'
END AS age_group
FROM users
ORDER BY age
/*
Почему удобнее держать логику сегментации в SQL (CASE), а не только в коде приложения?
Возможно, Так проще работать с данными
Что произойдёт, если в CASE забыть ветку ELSE (что получат пользователи, не попавшие ни в одно условие)?
У них появятся значения NULL
*/
--task 4
--Задача 4. «Горячие» пользователи по дате и активности
SELECT
name,
created_at::date AS created_date,
CURRENT_DATE - created_at::date AS days_since_registration,
CASE
WHEN (is_active IS TRUE OR CURRENT_DATE - created_at::date <= 30) THEN 'hot'
ELSE 'regular'
END AS hot_flag
FROM users
WHERE (is_active IS TRUE OR CURRENT_DATE - created_at::date <= 30)
/*Чем отличается фильтрация по дате в WHERE от простого CASE с меткой 'hot', но без фильтрации?
Последовательностью выполнения, различными функциями (в одном фильтрация идет, в другом просто присваивание определенному условию наименования в дополнительном столбце)
Какие типы рассылок/кампаний логично запускать только на «горячих»?
*/
--task 5
--Задача 5. Качество данных по email
SELECT
COUNT(*) AS total_users,
COUNT(email) AS with_email,
COUNT(*) - COUNT(email) AS without_email,
(COUNT(*) - COUNT(email)) * 100.0 / COUNT(*) AS dolya
FROM users
/*Почему для проверки «долей» и «заполненности» полей лучше использовать агрегаты в SQL, а не просто «на глаз» смотреть на таблицу?
То ли я туп, то ли вопрос с подковыркой для меня. Если значений может быть миллион, то как еще это делать, если не через агрегаты?
Какие действия по данным ты бы предложил продукту, если доля пользователей без email слишком большая?
Как минимум при регистрации сделать поле "имэйл" обязательным для заполнения.
*/
--task 6
--Задача 6. «Стаж» пользователя и его группа
SELECT
name,
CURRENT_DATE - created_at::date AS says_since_registration,
CASE
WHEN CURRENT_DATE - created_at::date <= 30 THEN 'new'
WHEN CURRENT_DATE - created_at::date > 180 THEN 'old'
ELSE 'middle'
END AS tenure_group,
is_active
FROM users
ORDER BY tenure_group, says_since_registration
/*
Чем сегментация по «стажу» отличается по смыслу от сегментации по возрасту?
Если пересчитывать tenure_group прямо в SQL каждый день, какие плюсы и минусы по сравнению с хранением статического поля segment?
Можно будет понимать в динамике сколько старичков и сколько молодых, можно будет видеть приросты пользователей за каждый день.
*/