исправлены предыдущие ошибки, добавлен полностью блок по кликхаус и пет-проект

This commit is contained in:
Dmitry Medvedev
2026-09-15 15:34:46 +05:00
parent 297df348c1
commit fb0f37912d
11 changed files with 1235 additions and 2 deletions
+230
View File
@@ -0,0 +1,230 @@
# Задачи на отработку:
### **Задача 1.**
Есть таблица `users`:
| user_id | name | age | country | is_active |
| --- | --- | --- | --- | --- |
| 1 | Ivan | 30 | RU | 1 |
| 2 | Anna | 25 | RU | 1 |
| 3 | Petr | 45 | RU | 0 |
| 4 | Olga | 35 | RU | 1 |
| 5 | John | 55 | US | 1 |
| 6 | Alice | 42 | US | 0 |
| 7 | Tom | 38 | US | 1 |
| 8 | Lucas | 28 | BR | 1 |
| 9 | Maria | 60 | BR | 1 |
| 10 | João | 27 | BR | 0 |
| 11 | Kenji | 33 | JP | 1 |
| 12 | Yuki | 29 | JP | 0 |
| 13 | Chen | 40 | CN | 1 |
| 14 | Li | 48 | CN | 1 |
| 15 | Fatima | 31 | AE | 1 |
| 16 | Ahmed | 36 | AE | 1 |
| 17 | George | 24 | US | 1 |
| 18 | Nina | 34 | RU | 1 |
| 19 | Max | 50 | DE | 1 |
| 20 | Sophie | 22 | DE | 0 |
CREATE TABLE users (
user_id UInt64,
name String,
age UInt32,
country String,
is_active UInt32
)
ENGINE = MergeTree()
ORDER BY (age, country);
1. Получи 10 самых старших **активных** пользователей.
SELECT
user_id,
name,
age
FROM users
WHERE is_active = 1
ORDER BY age DESC
LIMIT 10;
2. Выведи пользователей из `country = 'RU'`, отсортированных по имени.
SELECT
user_id,
name
FROM users
WHERE country = 'RU'
ORDER BY name;
3. Что произойдёт, если написать `LIMIT 10` **без `ORDER BY`**?
В таком случае CH покажет 10 произвольных неотсортированных строк
4. Посчитай количество пользователей по странам.
SELECT
country,
COUNT(*)
FROM users
GROUP BY country;
5. Для каждой страны выведи минимальный и максимальный возраст.
SELECT
country,
MIN(age),
MAX(age)
FROM users
GROUP BY country;
6. Отсортируй страны по убыванию количества пользователей.
SELECT
country,
COUNT(*)
FROM users
GROUP BY country
ORDER BY COUNT(*) DESC;
📌 Дополнительно:
- Используй `count()`, `min()`, `max()`, `sum()`
- Попробуй `uniqExact(country)` — что он делает?
uniqExact выводит количество уникальных значений, это тоже самое что и DISTINCT
### **Задача 2.**
Есть таблица `events`:
| user_id | event_time | event_type |
| --- | --- | --- |
| 1 | 2025-07-17 09:00:00 | click |
| 1 | 2025-07-17 09:05:00 | view |
| 1 | 2025-07-17 09:10:00 | purchase |
| 2 | 2025-07-17 10:00:00 | click |
| 2 | 2025-07-17 10:05:00 | click |
| 2 | 2025-07-17 11:00:00 | view |
| 3 | 2025-07-16 12:00:00 | view |
| 3 | 2025-07-16 12:30:00 | click |
| 3 | 2025-07-17 08:00:00 | purchase |
| 4 | 2025-07-17 13:00:00 | click |
| 4 | 2025-07-17 14:00:00 | view |
| 4 | 2025-07-17 15:00:00 | view |
| 5 | 2025-07-16 20:00:00 | view |
| 5 | 2025-07-17 01:00:00 | click |
| 5 | 2025-07-17 06:00:00 | purchase |
| 6 | 2025-07-17 07:30:00 | view |
| 6 | 2025-07-17 08:45:00 | click |
| 7 | 2025-07-16 23:59:59 | click |
| 7 | 2025-07-17 00:01:00 | purchase |
| 7 | 2025-07-17 10:10:00 | view |
CREATE TABLE events (
user_id UInt64,
event_type String,
event_time DateTime64(3)
)
ENGINE = MergeTree()
ORDER BY (event_time, user_id);
INSERT INTO dmedvedev.events (user_id, event_time, event_type) VALUES
(1, '2025-07-17 09:00:00', 'click'),
(1, '2025-07-17 09:05:00', 'view'),
(1, '2025-07-17 09:10:00', 'purchase'),
(2, '2025-07-17 10:00:00', 'click'),
(2, '2025-07-17 10:05:00', 'click'),
(2, '2025-07-17 11:00:00', 'view'),
(3, '2025-07-16 12:00:00', 'view'),
(3, '2025-07-16 12:30:00', 'click'),
(3, '2025-07-17 08:00:00', 'purchase'),
(4, '2025-07-17 13:00:00', 'click'),
(4, '2025-07-17 14:00:00', 'view'),
(4, '2025-07-17 15:00:00', 'view'),
(5, '2025-07-16 20:00:00', 'view'),
(5, '2025-07-17 01:00:00', 'click'),
(5, '2025-07-17 06:00:00', 'purchase'),
(6, '2025-07-17 07:30:00', 'view'),
(6, '2025-07-17 08:45:00', 'click'),
(7, '2025-07-16 23:59:59', 'click'),
(7, '2025-07-17 00:01:00', 'purchase'),
(7, '2025-07-17 10:10:00', 'view');
1. Добавь колонку с кумулятивным количеством событий по `user_id` (используй `count() OVER ...`).
SELECT
user_id,
COUNT() OVER (PARTITION BY user_id ORDER BY user_id)
FROM events;
2. Сделай аналог ранжирования событий внутри пользователя: `row_number() OVER (PARTITION BY user_id ORDER BY event_time)`
SELECT
user_id,
COUNT(*) OVER (PARTITION BY user_id ORDER BY event_time)
FROM events;
3. Что будет, если ты явно задашь `ROWS BETWEEN`? Поддерживается ли?
Посчитается, поддерживается.
SELECT
user_id,
COUNT(*) OVER (
PARTITION BY user_id ORDER BY event_time
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
)
FROM events;
4. Сделай `WITH recent_events AS (...)` — все события за последние 24 часа.
SELECT
user_id,
event_time
FROM events
WHERE event_time <= NOW() - INTERVAL 24 HOUR;
5. Используй CTE, чтобы посчитать топ-5 пользователей по числу этих событий.
WITH
recent_events AS (
SELECT
user_id,
event_type,
event_time
FROM events
WHERE event_time >= NOW() - INTERVAL 24 HOUR
)
SELECT
user_id,
COUNT(*)
FROM recent_events
GROUP BY user_id
ORDER BY COUNT(*) DESC
LIMIT 5;
6. Добавь второй `WITH` — для маппинга `event_type → category` и используй его в основном запросе.
WITH
recent_events AS (
SELECT
user_id,
event_type,
event_time
FROM events
WHERE event_time >= NOW() - INTERVAL 24 HOUR
),
top_users AS(
SELECT
user_id,
COUNT(*)
FROM recent_events
GROUP BY user_id
ORDER BY COUNT(*) DESC
LIMIT 5
)
SELECT
user_id,
CASE
WHEN event_type IN ('click', 'view') THEN 'interaction'
WHEN event_type IN ('purchase') THEN 'conversion'
ELSE 'unknown'
END AS category
FROM recent_events re INNER JOIN top_users tu ON re.user_id = tu.user_id;
📌 Вопрос: поддерживает ли ClickHouse **многоуровневые** или **рекурсивные** CTE?
МНОГОУРОВНЕВОСТЬ ЕСТЬ, А РЕКУРСИВНОСТИ НЕТ.