исправлены предыдущие ошибки, добавлен полностью блок по кликхаус и пет-проект
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
# Задачи на отработку:
|
||||
|
||||
### **Задача 1.**
|
||||
|
||||
Таблица `products`
|
||||
|
||||
| product_id | name |
|
||||
| --- | --- |
|
||||
| 101 | iPhone 14 |
|
||||
| 102 | Galaxy S22 |
|
||||
| 103 | Pixel 7 |
|
||||
|
||||
Таблица `prices`
|
||||
|
||||
| product_id | price | region |
|
||||
| --- | --- | --- |
|
||||
| 101 | 999 | US |
|
||||
| 101 | 1049 | EU |
|
||||
| 102 | 850 | US |
|
||||
| 102 | 899 | CA |
|
||||
| 103 | 799 | JP |
|
||||
1. Сделай `ANY LEFT JOIN`, чтобы получить цену **любой** из регионов.
|
||||
SELECT
|
||||
pr.product_id,
|
||||
p.region,
|
||||
pr.name,
|
||||
p.price
|
||||
FROM prices p
|
||||
ANY LEFT JOIN products pr ON p.product_id = pr.product_id;
|
||||
ЗДЕСЬ МЫ ПОЛУЧИМ НА ВЫХОДЕ 5 СТРОК.
|
||||
А ЕСЛИ БЫ ДЖОЙНИЛИ ТАБЛИЦЫ НАОБОРОТ, ТО ПОЛУЧИЛИ БЫ 3 СТРОКИ.
|
||||
|
||||
2. Что будет, если в таблице `prices` несколько цен на один `product_id`?
|
||||
ВСЕ БУДЕТ ЗАВИСЕТЬ ОТ СОЕДИНЕНИЯ ТАБЛИЦ. ЕСЛИ МЫ ДЖОЙНИМ К ТАБЛИЦЕ С product_id И НА КАЖДОЫЙ ЕСТЬ НЕСКОЛЬКО ЦЕН, ТО В ТАКОМ СЛУЧАЕ КЛИКХАУС ВОЗЬМЕТ ПЕРВОЕ ЗНАЧЕНИЕ С ДИСКА И ПРИСВОИТ ЕГО К product_id, А ОСТАЛЬНЫЕ ЗНАЧЕНИЯ ВЫБРОСИТ.
|
||||
|
||||
3. Как повлияет `ALL LEFT JOIN`? Почему в ClickHouse его избегают?
|
||||
ИЗ-ЗА ПРИМЕНЕНИЯ ОЛЛ ЛЕФТ ДЖОЙН КЛИКХАУС НЕ СМОЖЕТ ВЫБРОСИТЬ НЕНУЖНЫЕ СТРОКИ И УЧТЕТ ВСЕ. В НАШЕМ ПРИМЕРЕ СТРОК СТАНЕТ 5.
|
||||
ДАННЫЕ МОГУТ ПЕРЕГРУЖАТЬ ПАМЯТЬ И ТОРМОЗИТЬ СИСТЕМУ. МЕТРИКИ МОГУТ СЧИТАТЬСЯ ИСКАЖЕННЫМИ.
|
||||
|
||||
### **Задача 2.**
|
||||
|
||||
Таблица `ticks`
|
||||
|
||||
| time | symbol | price |
|
||||
| --- | --- | --- |
|
||||
| 2025-07-17 10:00:00 | AAPL | 190.5 |
|
||||
| 2025-07-17 10:01:00 | AAPL | 191.2 |
|
||||
| 2025-07-17 10:02:30 | AAPL | 192.0 |
|
||||
| 2025-07-17 10:05:00 | GOOG | 2850.0 |
|
||||
|
||||
Таблица `orders`
|
||||
|
||||
| time | symbol | size |
|
||||
| --- | --- | --- |
|
||||
| 2025-07-17 10:00:30 | AAPL | 50 |
|
||||
| 2025-07-17 10:02:00 | AAPL | 75 |
|
||||
| 2025-07-17 10:03:00 | AAPL | 20 |
|
||||
| 2025-07-17 10:04:00 | GOOG | 15 |
|
||||
1. Сделай `ASOF JOIN`, чтобы каждой сделке найти **предыдущую цену**.
|
||||
SELECT
|
||||
o.symbol,
|
||||
o.size,
|
||||
t.price,
|
||||
o.time AS order_time,
|
||||
t.time AS price_time
|
||||
FROM orders o
|
||||
ASOF LEFT JOIN ticks t ON o.symbol = t.symbol AND o.time >= t.time;
|
||||
|
||||
2. Почему нельзя использовать обычный `JOIN` по `time = time`?
|
||||
КАК МИНИМУМ ПОТОМУ ЧТО ВРЕМЯ ПО СДЕЛКЕ И ВРЕМЯ ПО ТИКЕТУ НЕ СОВПАДАЕТ.
|
||||
|
||||
3. Сделай выборку только по `symbol = 'AAPL'`.
|
||||
SELECT
|
||||
o.symbol,
|
||||
o.size,
|
||||
t.price,
|
||||
o.time AS order_time,
|
||||
t.time AS price_time
|
||||
FROM orders o
|
||||
ASOF LEFT JOIN ticks t ON o.symbol = t.symbol AND o.time >= t.time
|
||||
WHERE o.symbol = 'AAPL';
|
||||
|
||||
ИЛИ
|
||||
|
||||
SELECT
|
||||
o.symbol,
|
||||
o.size,
|
||||
t.price,
|
||||
o.time AS order_time,
|
||||
t.time AS price_time
|
||||
FROM
|
||||
(
|
||||
SELECT * FROM orders WHERE o.symbol = 'AAPL'
|
||||
) AS o
|
||||
ASOF LEFT JOIN
|
||||
(
|
||||
SELECT * FROM ticks WHERE o.symbol = 'AAPL'
|
||||
) AS t
|
||||
ON o.symbol = t.symbol AND o.time >= t.time;
|
||||
|
||||
### **Задача 3.**
|
||||
|
||||
Таблица `users`
|
||||
|
||||
| user_id | name |
|
||||
| --- | --- |
|
||||
| 1 | Alice |
|
||||
| 2 | Bob |
|
||||
| 3 | Charlie |
|
||||
| 4 | Diana |
|
||||
|
||||
Таблица `payments`
|
||||
|
||||
| payment_id | user_id | amount |
|
||||
| --- | --- | --- |
|
||||
| 1001 | 1 | 500 |
|
||||
| 1002 | 1 | 1500 |
|
||||
| 1003 | 3 | 1200 |
|
||||
| 1004 | 4 | 900 |
|
||||
1. Верни всех пользователей, у которых **есть платежи** (через `WHERE user_id IN (...)`).
|
||||
SELECT
|
||||
u.user_id
|
||||
FROM users u
|
||||
WHERE user_id IN (SELECT user_id FROM payments);
|
||||
|
||||
2. Добавь условие: сумма платежа больше 1000.
|
||||
SELECT
|
||||
u.user_id
|
||||
FROM users u
|
||||
WHERE user_id IN (SELECT user_id FROM payments WHERE amount > 1000);
|
||||
|
||||
3. Почему это называют `SEMI JOIN`? Как это оптимизируется в ClickHouse?
|
||||
Потому что это неполноценное соединение , а только проверяющее факт наличия того или иного условия.
|
||||
Вообще по идее нужно было бы написать LEFT SEMI JOIN , в кликхаус видя конструкцию IN (SELECT...) уже сам понимает что это SEMI JOIN.
|
||||
|
||||
### **Задача 4.**
|
||||
|
||||
Таблица `big_logs` (упрощённый фрагмент)
|
||||
|
||||
| user_id | event_time | event_type |
|
||||
| --- | --- | --- |
|
||||
| 1 | 2025-07-17 08:00:00 | login |
|
||||
| 2 | 2025-07-17 08:05:00 | view |
|
||||
| 3 | 2025-07-17 08:10:00 | purchase |
|
||||
| 1 | 2025-07-17 08:20:00 | logout |
|
||||
| 2 | 2025-07-17 08:30:00 | click |
|
||||
|
||||
Таблица `users`
|
||||
|
||||
| user_id | name |
|
||||
| --- | --- |
|
||||
| 1 | Alice |
|
||||
| 2 | Bob |
|
||||
| 3 | Charlie |
|
||||
1. Сделай `JOIN`, чтобы добавить `name` к каждому логу.
|
||||
SELECT
|
||||
bl.user_id,
|
||||
bl.event_time,
|
||||
bl.event_type,
|
||||
u.name
|
||||
FROM big_logs bl ANY LEFT JOIN users u ON bl.user_id = u.user_id;
|
||||
|
||||
2. Почему `users` нужно ставить **в правую часть JOIN**?
|
||||
ПОТОМУ ЧТО ЭТА ТАБЛИЦА ЯВЛЯЕТСЯ МАЛЕНЬКОЙ И МОЖНО СКАЗАТЬ СПРАВОЧНОЙ, А ЛОГИ БУДУТ РАСТИ И РАСТИ. И ЕСЛИ ЕЕ ЗАГРУЗИТЬ В ОПЕРАТИВНУЮ ПАМЯТЬ, ТО МЫ МОЖЕМ РАНО ИЛИ ПОЗДНО ПОЛУЧИТЬ ОШИБКУ.
|
||||
|
||||
3. Как выбрать `ANY` или `ALL` — если `user_id` уникален?
|
||||
ЕСЛИ МЫ УВЕРЕНЫ НА 100% ЧТО ОН УНИКАЛЕН ТО НУЖНО ВАЫБИРАТЬ ANY , В ТАКОМ СЛУЧАЕ СОХРАНЯЮТСЯ РЕСУРСЫ ПАМЯТИ. ALL ЖЕ ВЫБИРАЕТСЯ КОГДА НЕОБХОДИМО ДЕКАРТОВО ПРОИЗВЕДЕНИЕ.
|
||||
Reference in New Issue
Block a user