Files
homework/dmedvedev/clickhouse/4.CH_syntaxis.sql
T

230 lines
6.7 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Задачи на отработку:
### **Задача 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?
МНОГОУРОВНЕВОСТЬ ЕСТЬ, А РЕКУРСИВНОСТИ НЕТ.