mysql скользящая сумма кумулятивный сериализованный - PullRequest
0 голосов
/ 19 октября 2018

Например, у меня есть нижеприведенная таблица (tb_transaction)

id_trans    date_trans  production_plant    dead_plant  distribution_plant
25          2017-12-31  1000                100             200
26          2018-01-17  150                 0               0
27          2018-02-07  0                   50              100
28          2018-03-07  250                 0               75
29          2018-05-10  500                 50              0

Чем я пытаюсь составить таблицу отчетов за этот год, например, нижеприведенную таблицу

month   EarlyStock  production  dead    LivePlant   Distri  EndStock    
January                 150         0       150         0       150 
February                0           50      -50         100     -150    
March                   250         0       250         75      175 
April                   0           0       0           0       0   
May                     500         50      450         0       450 
June                    0           0       0           0       0   
July                    0           0       0           0       0   
August                  0           0       0           0       0   
September               0           0       0           0       0   
October                 0           0       0           0       0   
November                0           0       0           0       0   
December                0           0       0           0       0

Какие ранние запасы за январьEndStock декабрь 2017 года (предполагается, что EarlyStock для декабря равен 0), что является первыми данными из tb_transaction, а не EarlyStock за февраль - это EndStock January и т. д.

Моя ожидаемая таблица - Чем я пытаюсь создать таблицу отчета за этот год, как показано ниже:

month   EarlyStock  production  dead    LivePlant   Distri  EndStock    
January     700         150         0       850         0       850 
February    850         0           50      800         100     700 
March       700         250         0       950         75      875 
April       875         0           0       875         0       875 
May         875         500         50      1325        0       1325    
June                    0           0       0           0       0   
July                    0           0       0           0       0   
August                  0           0       0           0       0   
September               0           0       0           0       0   
October                 0           0       0           0       0   
November                0           0       0           0       0   
December                0           0       0           0       0

Формула:

  • LivePlant = EarlyStock + production - dead
  • EndStock = LivePlant - Distri

Любой Sugestion, как я могу это сделать?

Здесь db-скрипка для теста

1 Ответ

0 голосов
/ 19 октября 2018

Похоже, проблема скользящей суммы .Это можно сделать менее многословно, используя оконные функции в MySQL 8.0.2 и далее .Но, поскольку ваша версия MySQL 5.6 , мы можем эмулировать это поведение, используя определяемые пользователем переменные сеанса .

Основная суть этого метода:

  • Во-первых, в Производной таблице , вычислите сумму агрегированных сумм различных действий, таких как Dead, Distributed и т. Д. Для определенного года и месяца .В вашем случае у вас есть данные за разные годы, поэтому ваш подход к группировке по месяцам не сработает.Вам нужно сгруппировать по году и месяцу.Кроме того, ограничение набора результатов только текущим годом не поможет, так как вам потребуется конечная стоимость акций за декабрь месяц предыдущего года, чтобы получить раннюю стоимость акций за январь месяц следующего года.
  • Теперь, используйте набор результатов этого дополнительного запроса и определите Конечный запас и Ранний запас согласно вашим заданным определениям.Концептуально это похоже на написание кода приложения (например, PHP);мы используем значение Конечной акции предыдущей строки в качестве Раннего запаса для текущей строки.В конце установите значение Конечный запас для конечного запаса текущей строки (после вычисления).
  • Теперь, так как вам не нужна строка, соответствующая предыдущему году;Я бы посоветовал вам игнорировать эту строку в коде приложения.Тем не менее, если вы хотите обрабатывать это только в запросе;затем вам придется снова взять полный набор результатов в качестве производной таблицы и использовать Where, чтобы отфильтровать строки по годам, отличным от текущего года.

Попробуйте следующий код ( DB Fiddle DEMO ):

SELECT t1.year_no,
       t1.month_name,
       @early := @endst                             AS EarlyStock,
       @prod := t1.production                       AS production,
       @dead := t1.dead                             AS dead,
       ( @early + @prod - @dead )                   AS LivePlant,
       @dist := t1.distri                           AS Distri,
       @endst := ( @early + @prod - @dead - @dist ) AS EndStock
FROM   (SELECT Coalesce(Year(trans.date_trans), Year(CURRENT_DATE())) AS year_no,
               Coalesce(Month(trans.date_trans), mon.id_month) AS month_no,
               mon.month_name,
               Coalesce(Sum(trans.production_plant), 0)    AS production,
               Coalesce(Sum(trans.dead_plant), 0)          AS dead,
               Coalesce(Sum(trans.distribution_plant), 0)  AS Distri
        FROM   tb_month AS mon
               LEFT JOIN tb_transaction AS trans
                      ON Month(trans.date_trans) = mon.id_month
        GROUP  BY year_no,
                  month_no,
                  mon.month_name
        ORDER  BY year_no,
                  month_no) AS t1
       CROSS JOIN (SELECT @prod := 0,
                          @dead := 0,
                          @dist := 0,
                          @early := 0,
                          @endst := 0) AS user_init_vars  
...