← Назад к вопросам
SQL: Изменение в капитале при переводах между аккаунтами
1.7 Middle🔥 111 комментариев
#SQL и базы данных#Аналитика и метрики
Условие
Дана таблица транзакций переводов между аккаунтами:
CREATE TABLE transactions (
transaction_id INT PRIMARY KEY,
sender_id INT,
receiver_id INT,
amount DECIMAL(10,2),
transaction_date DATE
);
Пример данных:
| transaction_id | sender_id | receiver_id | amount | transaction_date |
|---|---|---|---|---|
| 1 | 100 | 200 | 500.00 | 2024-01-15 |
| 2 | 200 | 300 | 300.00 | 2024-01-16 |
| 3 | 300 | 100 | 200.00 | 2024-01-17 |
| 4 | 100 | 300 | 150.00 | 2024-01-18 |
Задание:
- Рассчитайте итоговое изменение баланса для каждого аккаунта (отправленное минус полученное)
- Найдите аккаунты с положительным и отрицательным балансом изменений
- Определите пару аккаунтов с максимальным объёмом переводов между собой
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Задача и подход
Нужно анализировать переводы между аккаунтами: рассчитать изменение баланса, определить положительные/отрицательные балансы и найти наиболее активные пары аккаунтов.
Шаг 1: Изменение баланса для каждого аккаунта
WITH account_cash_flow AS (
SELECT
account_id,
SUM(CASE WHEN flow_type = 'sent' THEN amount ELSE 0 END) AS total_sent,
SUM(CASE WHEN flow_type = 'received' THEN amount ELSE 0 END) AS total_received
FROM (
SELECT sender_id AS account_id, amount, 'sent' AS flow_type
FROM transactions
UNION ALL
SELECT receiver_id, amount, 'received'
FROM transactions
) flows
GROUP BY account_id
)
SELECT
account_id,
total_sent,
total_received,
total_sent - total_received AS balance_change
FROM account_cash_flow
ORDER BY balance_change DESC;
Результат: 100: -350, 200: +200, 300: +150
Шаг 2: Классификация на положительные и отрицательные
WITH balance_data AS (
SELECT
account_id,
SUM(CASE WHEN flow_type = 'sent' THEN amount ELSE 0 END) -
SUM(CASE WHEN flow_type = 'received' THEN amount ELSE 0 END) AS balance
FROM (
SELECT sender_id AS account_id, amount, 'sent' FROM transactions
UNION ALL
SELECT receiver_id, amount, 'received' FROM transactions
) flows
GROUP BY account_id
)
SELECT
account_id,
balance,
CASE WHEN balance > 0 THEN 'Negative' ELSE 'Positive' END AS balance_type
FROM balance_data
ORDER BY balance DESC;
Шаг 3: Пара аккаунтов с максимальным объёмом
SELECT
LEAST(sender_id, receiver_id) AS account_a,
GREATEST(sender_id, receiver_id) AS account_b,
SUM(amount) AS total_volume
FROM transactions
GROUP BY
LEAST(sender_id, receiver_id),
GREATEST(sender_id, receiver_id)
ORDER BY total_volume DESC
LIMIT 1;
Для примера: пара (100, 300) с объёмом 350 (100→300: 150, 300→100: 200)
Объяснение логики
Шаг 1: UNION объединяет отправки и получения как потоки денежных средств, затем группируем по account_id.
Шаг 2: Положительный баланс означает, что счёт получил больше, чем отправил. Отрицательный — отправил больше.
Шаг 3: LEAST/GREATEST нормализуют пары (100,200) и (200,100) в одну запись для правильной агрегации.