исправлены предыдущие ошибки, добавлен полностью блок по кликхаус и пет-проект
This commit is contained in:
@@ -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?
|
||||
МНОГОУРОВНЕВОСТЬ ЕСТЬ, А РЕКУРСИВНОСТИ НЕТ.
|
||||
Reference in New Issue
Block a user