Есть ли способ проверить совокупный способ получить месяц на основе полей суммы

У меня есть одна таблица, как показано ниже, MySQL

customer_id,invoice_id,invoice_month,payment_month,invoice_amount,payment_amt,balance_amt
1,1,"DEC 23","JAN 24",400.00,400.00,0.00
1,2,"DEC 23","JAN 24",600.00,600.00,0.00
1,3,"JAN 24","JAN 24",200.00,50.00,150.00
2,4,"SEP 23","MAY 24",800.00,800.00,0.00
2,5,"OCT 23","MAY 24",750.00,750.00,0.00
3,6,"FEB 24","MAY 24",925.00,525.00,400.00
4,7,"NOV 22","JUN 23",325.00,325.00,0.00
4,8,"DEC 22","JUN 23",425.00,425.00,0.00
5,9,"JUN 24",NULL,500.00,NULL,500.00

Таблица платежей как

customer_id,payment_month,amount
1,JAN 24,500
1,FEB 24,550
2,MAR 24,450
2,APR 24,900
2,MAY 24,450
3,MAY 24,525
4,JUN 23,350
4,JUN 23,400

необходимо создать новые столбцы «Payment_final_month» на основе «Payment_month» из таблицы платежей. Для первой записи у меня есть сумма счета-фактуры, равная 400, что меньше суммы в таблице платежей. Первая запись, затем выберите 24 января. Для второй записи, поскольку у меня осталось 100 от первой записи, выберите то же самое 24 января. Для третьей записи я должен выбрать 24 февраля.

Окончательный результат что-то вроде

customer_id invoice_id  invoice_month   payment_month   invoice_amount  payment_amt balance_amt payment_final_month
1   1   DEC 23  JAN 24  400.00  400.00  0.00    JAN 24
1   2   DEC 23  JAN 24  600.00  600.00  0.00    JAN 24
1   3   JAN 24  FEB 24  200.00  50.00   150.00  FEB 24
2   4   SEP 23  MAR 24  800.00  800.00  0.00    MAR 24
2   5   OCT 23  APR 24  750.00  750.00  0.00    APR 24
3   6   FEB 24  MAY 24  925.00  525.00  400.00  MAY 24
4   7   NOV 22  JUN 23  325.00  325.00  0.00    JUN 23
4   8   DEC 22  JUN 23  425.00  425.00  0.00    JUN 23
5   9   JUN 24  NULL    500.00  NULL    500.00  NULL

Я попробовал подход ниже и не сработал

i.invoice_amount - COALESCE(LAG(i.payment_amt, 1) OVER (PARTITION BY i.customer_id ORDER BY i.invoice_id), 0) AS remaining_amount

Можете ли вы изменить дизайн, чтобы включить даты в качестве типа данных даты и сохранить фактические даты?

P.Salmon 20.06.2024 14:10

@P.Salmon . Большое спасибо за ответ. Возможно, я не смогу вносить изменения в даты, поскольку у меня есть даты в том же формате: МОН ГГ. Есть ли какое-нибудь предложение, которое вы можете мне помочь?..

Arya 20.06.2024 14:11

@ysth. Большое спасибо за комментарий. Есть ли какое-нибудь предложение, я могу попробовать, пожалуйста

Arya 20.06.2024 15:25

@ysth 100 следует учитывать для следующей записи. Поскольку часть 1-й записи из 500 400 меньше 500, а осталось 100, и в качестве причины для 2-й записи также следует выбрать 24 января. Он должен идти в порядке возрастания и выбирать следующее по величине значение на основе разницы Счет с оплатой

Arya 20.06.2024 15:35

У счета-фактуры 2 было 100 оплачено 24 января, а оставшиеся 500 оплачено 24 февраля. Почему платеж_final_month должен быть 24 января?

ysth 20.06.2024 23:27

у вас действительно нет первичного ключа для таблицы платежей?

ysth 20.06.2024 23:28
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
6
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это немного запутанно, потому что есть некоторые проблемы с дизайном, связанные с ключами, связями и (особенно) датами.
Чтобы решить эту проблему, вам следует преобразовать строки месяца в типы данных даты. Один из способов сделать это — использовать cte для преобразования типов данных даты и расчета текущих сумм (кумулятивов) для сумм счетов и платежей.
Итак, с вашим примером данных:

WITH    --  S a m p l e    D a t a :
    invoices (customer_id, invoice_id, invoice_month, payment_month, 
              invoice_amount, payment_amt, balance_amt) AS
      ( Select 1, 1, 'DEC 23', 'JAN 24', 400.00, 400.00,   0.00 Union All 
        Select 1, 2, 'DEC 23', 'JAN 24', 600.00, 600.00,   0.00 Union All
        Select 1, 3, 'JAN 24', 'JAN 24', 200.00,  50.00, 150.00 Union All
        Select 2, 4, 'SEP 23', 'MAY 24', 800.00, 800.00,   0.00 Union All
        Select 2, 5, 'OCT 23', 'MAY 24', 750.00, 750.00,   0.00 Union All
        Select 3, 6, 'FEB 24', 'MAY 24', 925.00, 525.00, 400.00 Union All
        Select 4, 7, 'NOV 22', 'JUN 23', 325.00, 325.00,   0.00 Union All
        Select 4, 8, 'DEC 22', 'JUN 23', 425.00, 425.00,   0.00 Union All
        Select 5, 9, 'JUN 24', NULL,     500.00, NULL,   500.00
      ), 
    payments (customer_id, payment_month, amount) AS
      ( Select 1, 'JAN 24', 500 Union All
        Select 1, 'FEB 24', 550 Union All
        Select 2, 'MAR 24', 450 Union All
        Select 2, 'APR 24', 900 Union All
        Select 2, 'MAY 24', 450 Union All
        Select 3, 'MAY 24', 525 Union All
        Select 4, 'JUN 23', 350 Union All
        Select 4, 'JUN 23', 400
      ), 

... сначала создайте cte, который будет использоваться для преобразования месяцев в даты...

--  months conversion cte
    dates (mon, mm) AS
      ( Select  'JAN', '01' Union All
        Select  'FEB', '02' Union All
        Select  'MAR', '03' Union All
        Select  'APR', '04' Union All
        Select  'MAY', '05' Union All
        Select  'JUN', '06' Union All
        Select  'JUL', '07' Union All
        Select  'AUG', '08' Union All
        Select  'SEP', '09' Union All
        Select  'OCT', '10' Union All
        Select  'NOV', '11' Union All
        Select  'DEC', '12' 
      ), 

... затем создайте еще два CTE для преобразования дат (используя указанный выше CTE) и для просчета сумм счетов и сумм платежей...

--  prepare payment data (cumulative sums and dates)
    payments_cumul AS
      ( Select p.customer_id, p.payment_month, p.amount, 
               STR_TO_DATE( Concat('01', d.mm, SubStr(p.payment_month, 5, 2)), '%d%m%y' ) as pay_date, 
               Sum(p.amount) Over(Partition By p.customer_id 
                                 Order By STR_TO_DATE( Concat('01', d.mm, SubStr(p.payment_month, 5, 2)), '%d%m%y' )
                                Rows Between Unbounded Preceding And Current Row) as pay_amt_cumul
        From   payments p
        Inner Join dates d ON( d.mon = SubStr(p.payment_month, 1, 3))
      ),
--  prepare invoice data (cumulative sums and dates)
    grid as
      ( Select    i.customer_id, i.invoice_id, 
                  i.invoice_month, i.payment_month as inv_payment_month, 
                  i.invoice_amount, 
                  Sum(i.invoice_amount) Over( Partition By i.customer_id, i.payment_month
                                              Order By STR_TO_DATE( Concat('01', d.mm, SubStr(i.payment_month, 5, 2)), '%d%m%y' )
                                              Rows Between Unbounded Preceding And Current Row
                                            ) as inv_amt_cumul,
                  i.payment_amt, i.balance_amt,
                  STR_TO_DATE( Concat('01', d.mm, SubStr(i.payment_month, 5, 2)), '%d%m%y' ) as inv_pay_date
        From      invoices i
        Left Join dates d ON( d.mon = SubStr(i.payment_month, 1, 3) )
      ) 

... наконец, соедините все это вместе, агрегируйте и сгруппируйте по...

--    M a i n    S Q L :
Select    g.customer_id, g.invoice_id,  
          Max(g.invoice_month) as invoice_month, 
          g.inv_payment_month,
          g.invoice_amount, g.payment_amt, g.balance_amt, 
          DATE_FORMAT(Case When g.inv_amt_cumul - Max(Coalesce(p.pay_amt_cumul, 0)) > 0
               Then Coalesce(Max(p.pay_date), g.inv_pay_date)  
          Else g.inv_pay_date
          End, '%M %y')  as payment_final_month
From      grid g
Left Join payments_cumul p ON( p.customer_id = g.customer_id And 
                               g.inv_amt_cumul >= p.pay_amt_cumul  
                             )
Group By g.customer_id, g.invoice_id, g.inv_payment_month, g.inv_pay_date, 
         g.invoice_amount, g.payment_amt, g.balance_amt
Order By g.customer_id, g.invoice_id
/*    R e s u l t :
customer_id invoice_id  invoice_month   inv_payment_month   invoice_amount  payment_amt balance_amt payment_final_month
----------- ----------  --------------  ------------------  --------------  ----------- ----------- -------------------
1                    1  DEC 23          JAN 24                      400.00       400.00        0.00 January 24
1                    2  DEC 23          JAN 24                      600.00       600.00        0.00 January 24
1                    3  JAN 24          JAN 24                      200.00        50.00      150.00 February 24
2                    4  SEP 23          MAY 24                      800.00       800.00        0.00 March 24
2                    5  OCT 23          MAY 24                      750.00       750.00        0.00 April 24
3                    6  FEB 24          MAY 24                      925.00       525.00      400.00 May 24
4                    7  NOV 22          JUN 23                      325.00       325.00        0.00 June 23
4                    8  DEC 22          JUN 23                      425.00       425.00        0.00 June 23
5                    9  JUN 24          null                        500.00         null      500.00 null        */

См. скрипку здесь.

ОБНОВЛЕНИЕ: (Код ошибки: 1270. Недопустимое сочетание параметров сортировки)
смешанная сортировка внутри функции Concat() вызывает ошибку. Первые две строки в concat — utf8, а третья — latin1. Используйте явное сопоставление либо для первых двух, либо для третьего и сделайте их одинаковыми (все 4 объединения в коде):

STR_TO_DATE( Concat('01',   -- utf8
                    d.mm,   -- utf8
                    SubStr(p.payment_month COLLATE utf8mb4_0900_ai_ci, 5, 2)), 
           '%d%m%y' )

ИЛИ

STR_TO_DATE( Concat('01'  COLLATE latin1_swedish_ci, 
                    d.mm  COLLATE latin1_swedish_ci, 
                    SubStr(p.payment_month, 5, 2)),   -- latin1
            '%d%m%y' )

@d r, спасибо большое. Я попробовал и получил ошибку с кодом ошибки: 1270. Недопустимое сочетание параметров сортировки (utf8mb4_0900_ai_ci,COERCIBLE), (utf8mb4_0900_ai_ci,COERCIBLE), (latin1_swedish_ci,IMPLICIT) для операции 'concat'

Arya 21.06.2024 20:44

@Arya Только что опубликовала сообщение об этой ошибке.

d r 22.06.2024 08:51

Другие вопросы по теме