Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.09.2023, 01:40   #1
xakon_by
Новичок
Джуниор
 
Регистрация: 03.09.2023
Сообщений: 1
По умолчанию SQL подсчёт остатка и прибыли в каждый день месяца

Есть очень плохо спроектированная БД Для системы, позволяющей выдавать займы, учитывать суммы выдач и выплат и т.д.

Что есть займ (loan). Некоторая сумма денег(основной долг, ОД, MD), которую клиент берет в долг у организации под определенный процент (INT), и постепенно выплачивает суммы, указанные в заранее сформированном графике платежей. Часть платежа уходит на погашение ОД, часть на погашение начисленных процентов. Если человек не заплатил/заплатил не полностью сумму по графику, то начисляется пеня (PEN), еще может начисляться комиссия (COM).

Каждая подобная операция вносится в таблицу Operations. При этом, разрабатывая эту систему, как то забыли добавить сущность счета и балансов, что сильно облегчило бы жизнь)
Поэтому баланс на каждом абстрактном “типе счета” приходится считать, как сумма всех операций.

Задача:
Написать запрос, который для каждого дня без пропусков*, начиная с минимального значения Operations.created_at, и заканчивая текущим днем, посчитает портфель (только текущий остаток по ОД), а также общую прибыль (сумма дохода от остальных типов операций)

портфель = весь outcome по счету ОД - income по счету ОД
прибыль = income остальных типов операций

DDL:
create table Operations (
id number,
loan_id number,
is_income_flg char(1), -- 1/0
type varchar(3), -- MD/INT/PEN/COM
created_at date,
amount number(15, 2)
);

Пример:
1. 2 клиента взяли кредиты по 1000 $.
2. По графику платеж спустя 2 дня, 1 клиент внес - 100 $ (70 - ОД, 30 - проценты)
3. Результат
Дата Портфель Прибыль
2023-01-01 2000 0
2023-01-02 2000 0
2023-01-03 1930 30

Код:
CREATE TABLE Operations (
    id INT(10),
    loan_id INT(10),
    is_income_flg CHAR(1),
    TYPE VARCHAR(3),
    created_at DATE,
    amount DOUBLE(15,2)
);
 
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (1, 1, '0', 'MD', '2023-07-01', 1000.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (2, 1, '1', 'MD', '2023-07-03', 70.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (3, 1, '1', 'INT', '2023-07-03', 30.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (5, 1, '1', 'PEN', '2023-07-03', 2.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (6, 2, '0', 'MD', '2023-07-07', 500.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (7, 2, '1', 'MD', '2023-07-10', 400.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (8, 2, '1', 'INT', '2023-07-12', 100.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (9, 3, '0', 'MD', '2023-07-12', 300.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (10, 3, '1', 'MD', '2023-08-13', 300.0);
INSERT INTO operations (id, loan_id, is_income_flg, TYPE, created_at, amount) VALUES (11, 3, '1', 'INT', '2023-08-13', 30.0);
Получившийся результат запроса, как я понимаю задание, должен выглядеть вот так:

Дата Портфель Прибыль
2023-07-01 1000.0 0
2023-07-02 1000.0 0
2023-07-03 930 102
2023-07-04 930 102
2023-07-05 930 102
2023-07-06 930 102
2023-07-07 1430 102
2023-07-08 1430 102
2023-07-09 1430 102
2023-07-10 1030 102
2023-07-11 1030 102
2023-07-12 1030 202
2023-07-13 1330 232




Код:
WITH RECURSIVE nrows(date) AS (
SELECT MAKEDATE(2021,333) UNION ALL 
SELECT DATE_ADD(date,INTERVAL 1 day) FROM nrows WHERE  date<=CURRENT_DATE
)
SELECT 

    date as cur_date,
    SUM(CASE WHEN type = 'MD' AND is_income_flg = '0' THEN amount ELSE 0 END) AS total_outcome,
    SUM(CASE WHEN type = 'MD' AND is_income_flg = '1' THEN amount ELSE 0 END) AS total_income,
    SUM(CASE WHEN type != 'MD' THEN amount ELSE 0 END) AS total_profit
FROM 
    Operations
    right join nrows on created_at=date
WHERE 
    created_at >= (SELECT MIN(created_at) FROM Operations) AND created_at <= CURDATE()
    group by cur_date
Условия (case when) не совсем верные, но проблема не в этом. Подскажите как вообще связать или реализовать вывод всех дней месяца, но при этом подсчитывая портфель и прибыль с учётом предыдущих.

Последний раз редактировалось xakon_by; 03.09.2023 в 01:45.
xakon_by вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
[РЕШЕНО] Джон взял кредит в банке на сумму А под Р% в день. Каждый седьмой день он будет возвращать некоторую сумму В. Сможет ли Джон рассчитаться с банком kim-im Паскаль, Turbo Pascal, PascalABC.NET 2 20.12.2018 13:19
есть 200 тонн цемента, в первый день я трачу 5 тонн, дальше каждый день на 20% больше. Как при помощи цикла while заставить программу показать, через сколько дней цемент кончится? LaSTiqq Паскаль, Turbo Pascal, PascalABC.NET 3 21.04.2017 17:47
С++ Лыжник, начав тренировки, в первый день пробежал n км. Каждый следующий день он увеличивал пробег на m% от пробега предыдущего дня. Сколько километров он пробежит за k дней. marina46 Помощь студентам 9 23.11.2016 18:27
Последний день месяца kzld Microsoft Office Excel 5 28.02.2013 12:14
определить день недели по заданному числу (считать в месяце 30 дней и первый день месяца понедельник dan1991 Помощь студентам 1 01.03.2009 20:59