Add homework on SQL Functions: dates, strings, logic

This commit is contained in:
valera.beretar
2026-05-25 19:14:57 +03:00
parent c0f5f0dc5e
commit 1bc7c5f3fe
@@ -0,0 +1,89 @@
-- 1 Задача
SELECT name,
CAST(created_at AS date) AS created_date,
CURRENT_DATE - CAST(created_at AS date) AS days_since_registration
FROM users
WHERE created_at <= CURRENT_DATE - INTERVAL '180 days'
ORDER BY days_since_registration DESC;
-- Ответ на вопросы
-- 1. Возможно предложить старым пользователям скидки всякие или интересное предложение для удержания пользователям. Или можно проанализировать их заказы.
-- 2. Я предположу что удобней не марочится со временем а сразу работать с датой
-- 2 Задача
SELECT name,
LOWER(email) AS email_clean,
SUBSTRING(email FROM POSITION('@' IN email) + 1) AS domain
FROM users
WHERE email IS NOT NULL
ORDER BY domain, name;
-- Ответ на вопросы
-- 1. Приводим email к нижнему регистру для чистоты данных,
-- а зачем нужен отдельно домен не знаю, может есть какая нибудь важная разница в почтовых сервисах.
-- 2. Получим в колонке domain null.
-- 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;
-- Ответ на вопросы
-- 1. Возможно данные и статистику быстрее и удобнее получить через sql а не через код приложения.
-- 2. Пользователи получат null в колонке, оно просто не пройдет условие.
-- 4 Задача
SELECT name,
created_at::date AS created_date,
CURRENT_DATE - created_at::date AS days_since_registration,
CASE
WHEN is_active = TRUE THEN 'hot'
ELSE 'regular'
END AS hot_flag
FROM users
WHERE is_active = TRUE
AND created_at >= CURRENT_DATE - INTERVAL '30 days';
-- Ответ на вопросы
-- 1. В WHERE мы получим только пользователей за последние 30 дней а в CASE мы просто получаем метку 'hot' или 'regular'.
-- И в CASE мы не фильтруем по каким либо параметрам а только прописываем условие что записать.
-- 2. Какие нибудь рекомендации или скидку на первый заказ.
-- 5 Задача
SELECT COUNT(*) AS total_users,
COUNT(email) AS with_email,
COUNT(*) - COUNT(email) AS without_email,
ROUND(COUNT(country) * 100.0 / COUNT(*), 2) AS percentage_users
FROM users;
-- Ответ на вопросы
-- 1. Так гораздо надежнее и правильнее.
-- 2. Установить ограничение на создание пользователя, чтоб поле email было не нулевым.
-- 6 Задача
SELECT name,
CURRENT_DATE - created_at::date AS days_since_registration,
CASE
WHEN created_at >= CURRENT_DATE - INTERVAL '30 days' THEN 'new'
WHEN created_at < CURRENT_DATE - INTERVAL '30 days'
AND created_at > CURRENT_DATE - INTERVAL '180 days' THEN 'middle'
WHEN created_at < CURRENT_DATE - INTERVAL '180 days' THEN 'old'
END AS tenure_group,
is_active
FROM users
ORDER BY created_at >= CURRENT_DATE - INTERVAL '30 days',
created_at < CURRENT_DATE - INTERVAL '30 days'
AND created_at > CURRENT_DATE - INTERVAL '180 days',
created_at < CURRENT_DATE - INTERVAL '180 days',
days_since_registration;
-- Ответ на вопросы
-- 1. В сегментации по возрасту показывает возраст пользователя,
-- а в сегментации стаж показывает на сколько долго пользователь пользуется сервисом(приложением)
-- 2. CURRENT_DATE показывает сегодняшний день и если tenure_group пользоваться каждый день, то будет смещатся интервал в логическом выражении CASE.
-- В статическом поле дание остаются записанными пока их не изменят, течение времени на них никак не будет влиять.