Допустим, у вас есть таблица
transactions:
CREATE TABLE transactions (
id SERIAL PRIMARY KEY,
user_id INT,
amount NUMERIC,
status TEXT,
created_at TIMESTAMP
);
🎯 Задача:
Для каждой транзакции нужно найти максимальный
amount:- За последние 7 дней, включая текущую
- Только по этому же
user_id - Только по статусу
'confirmed'📥 Ожидаемый вывод:
| id | user_id | amount | created_at | max_amount_last_7d |
|----|---------|--------|--------------------|---------------------|
| 1 | 101 | 100 | 2024-01-01 10:00 | 100 |
| 2 | 101 | 150 | 2024-01-04 12:00 | 150 |
| 3 | 101 | 120 | 2024-01-07 09:00 | 150 |
| 4 | 101 | 90 | 2024-01-15 14:00 | 120 |
🧩 Решение:
SELECT
t1.id,
t1.user_id,
t1.amount,
t1.created_at,
(
SELECT MAX(t2.amount)
FROM transactions t2
WHERE t2.user_id = t1.user_id
AND t2.status = 'confirmed'
AND t2.created_at BETWEEN t1.created_at - INTERVAL '7 days' AND t1.created_at
) AS max_amount_last_7d
FROM transactions t1;
⚠️ Подводные камни:
- Без индексов по
user_id, status, created_at запрос будет тормозить - Используется подзапрос, а не
window function, потому что окно — динамическое - В PostgreSQL стоит учитывать точные границы
BETWEEN при сравнении времени🚀 Навыки, которые проверяются:
- Оптимизация временных окон
- Группировка и фильтрация с условиями
- Агрегации по диапазонам
💡 Усложнение:
Хочешь ещё интереснее? Добавь группировку по разным
status, или перепиши на JOIN с LATERAL.