Собесов

Альфа-Банк SQL — клиенты Москвы с суммарным остатком от 20000

SQLАгрегация и фильтрацияЛёгкаяMiddle

Условие

Дано две таблицы. Клиенты — справочник клиентов и их счетов (одна строка на пару клиент-счёт), Cчета — история состояний счёта на конкретные даты.

create table #Клиенты (
  client_id   varchar(1),
  FIO         varchar(255),
  Region      varchar(50),
  account_num int
);
 
create table #Cчета (
  [Date]      date,
  Summa_USD   money,
  Account_num int
);

Нужно отобрать клиентов из г. Москва с суммарным остатком по всем счетам клиента ≥ 20 000 на последнюю доступную дату.

Тестовые данные

client_id FIO Region account_num
A Иванов Москва 111
A Иванов Москва 222
B Петров Иваново 333
C Сидоров Москва 444
Date Summa_USD Account_num
2012-01-01 15000 111
2012-02-01 10000 111
2012-02-01 5000 222
2012-03-01 30000 333
2012-04-01 20000 444

Решение

Подход

«Последняя доступная дата» в задании двусмысленна: это max(date) по счёту или по всей таблице? Разумная интерпретация — по каждому счёту берём последний снимок, потом суммируем по клиенту.

Реализация

WITH last_balance AS (
  -- Последний снимок по каждому счёту
  SELECT
    Account_num,
    Summa_USD,
    ROW_NUMBER() OVER (PARTITION BY Account_num ORDER BY [Date] DESC) AS rn
  FROM #Cчета
),
client_total AS (
  SELECT
    k.client_id,
    MAX(k.FIO) AS FIO,
    SUM(b.Summa_USD) AS total_balance
  FROM #Клиенты k
  JOIN last_balance b ON b.Account_num = k.account_num AND b.rn = 1
  WHERE k.Region = 'Москва'
  GROUP BY k.client_id
)
SELECT client_id, FIO, total_balance
FROM client_total
WHERE total_balance >= 20000;

Проверка

  • Иванов (Москва): счёт 111 — последний остаток 10 000 (за февраль), счёт 222 — 5 000. Сумма = 15 000. Не проходит.
  • Сидоров (Москва): счёт 444 — 20 000. Проходит.
  • Петров (Иваново) — отбрасывается по региону.

Ответ: C, Сидоров, 20000.

Подводные камни

  1. Что такое «последняя дата». Глобальный max(date) по таблице может относиться вообще к другому счёту, и для счёта 111 пришлось бы взять остаток 0 (нет записи). У задачи нужно явно проговорить интерпретацию.
  2. Дубль клиента. Один client_id встречается с разными account_num — нельзя сравнивать Summa_USD каждой строки с 20 000 поодиночке, нужна сумма по клиенту.
  3. Region может содержать пробелы / разный регистрWHERE Region = 'Москва' строгое равенство; в проде лучше LOWER(TRIM(Region)) = 'москва'.
  4. HAVING vs подзапрос. Можно сразу SELECT ... FROM ... GROUP BY client_id HAVING SUM(...) >= 20000, но «последний остаток» требует оконки.

Эталонный ответ

CTE с ROW_NUMBER() OVER (PARTITION BY Account_num ORDER BY Date DESC) для последнего снимка → JOIN с клиентами, фильтр по Москве → агрегат SUM по клиенту → фильтр >= 20000.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти