【问题标题】:MySql Window Functions- Running total for a period using window framesMySql 窗口函数 - 使用窗口框架运行一段时间的总计
【发布时间】:2021-05-28 04:59:18
【问题描述】:

我需要在可能没有每个月数据的表中计算 3 个月的运行总计。 框架可以定义为 period- 2 个月和 periodEnd 之间的 periodEnd

这是期望的结果: |BuyerID |RecType |PeriodEnd |金额 |3Month |:---- |:--------| -----:| -----:| -----:| |100002|开放式AR| 2019-03-31| 1500.00| 1500.00| |100002|开放式AR| 2019-10-31| 50.00| 50.00| |100002|开放式AR| 2020-10-31| 150.00| 150.00| |100002|开放式AR| 2020-11-30| 162.00| 312.00| |100002|开放式AR| 2021-02-28| 50.00| 50.00| ...

 CREATE TABLE `ARSummary` (
  `BuyerID` varchar(17) NOT NULL,
  `RecType` varchar(10) NOT NULL,
  `PeriodEnd` date NOT NULL,
  `Amount` decimal(19,2) NOT NULL,
  PRIMARY KEY (`BuyerID`,`RecType`,`PeriodEnd`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO ARSummary (BuyerID, RecType, PeriodEnd, Amount) 
values('100002', 'OpenAR', '2019-03-31', 1500.00)
,('100002', 'OpenAR', '2019-10-31', 50.00)
,('100002', 'OpenAR', '2020-10-31', 150.00)
,('100002', 'OpenAR', '2020-11-30', 162.00)
,('100002', 'OpenAR', '2021-02-28', 50.00)
,('100002', 'OpenAR', '2021-03-31', 250.00)
,('100002', 'OpenAR', '2021-04-30', 150.00)
,('100002', 'Revenue', '2019-02-28', 1500.00)
,('100002', 'Revenue', '2019-10-31', 50.00)
,('100002', 'Revenue', '2020-10-31', 150.00)
,('100002', 'Revenue', '2020-11-30', 12.00)
,('100002', 'Revenue', '2021-02-28', 50.00)
,('100002', 'Revenue', '2021-03-31', 200.00)
,('100004', 'OpenAR', '2019-01-31', 890.00)
,('100004', 'OpenAR', '2019-03-31', 150.00)
,('100004', 'OpenAR', '2019-04-30', 450.00)
,('100004', 'OpenAR', '2019-05-31', 300.00)
,('100004', 'Revenue', '2019-03-31', 150.00)
,('100004', 'Revenue', '2019-04-30', 300.00);

我试过了

select BuyerID, RecType, PeriodEnd, Amount, sum(Amount) over (PARTITION by  BuyerID , RecType ORDER BY BuyerID , RecType, PeriodEnd  ROWS BETWEEN 3 PRECEDING and 0 FOLLOWING) as 3Month
from ARSummary 

CREATE OR REPLACE VIEW generator_16
AS SELECT 0 n UNION ALL SELECT 1  UNION ALL SELECT 2  UNION ALL 
   SELECT 3   UNION ALL SELECT 4  UNION ALL SELECT 5  UNION ALL
   SELECT 6   UNION ALL SELECT 7  UNION ALL SELECT 8  UNION ALL
   SELECT 9   UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL
   SELECT 12  UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL 
   SELECT 15;

CREATE OR REPLACE VIEW generator_256
AS SELECT ( ( hi.n << 4 ) | lo.n ) AS n
     FROM generator_16 lo, generator_16 hi;

    select D.Dt, S.BuyerID, S.RecType, S.PeriodEnd, S.Amount, sum(Amount) over (PARTITION by BuyerID , RecType ORDER BY D.Dt ROWS BETWEEN 2 PRECEDING and current ROW ) as 3Month
from (
select LAST_DAY( DATE_SUB(CURDATE(), interval n month)) as dt, b.BuyerID, 'OpenAR' as RecType from generator_256
cross join (select DISTINCT Buyerid from ARSummary) b 
where n < 37 
union select LAST_DAY( DATE_SUB(CURDATE(), interval n month)) as dt, b.BuyerID, 'Revenue' as RecType from generator_256
cross join (select DISTINCT Buyerid from ARSummary) b 
where n < 37 
) as D
left join     ARSummary  S 
on D.dt = S.PeriodEnd and D.BuyerId = S.BuyerID AND D.RecType = S.RecType 

我错过了什么?

【问题讨论】:

    标签: mysql partitioning windowing


    【解决方案1】:
        CREATE OR REPLACE
    ALGORITHM = UNDEFINED VIEW `FORTUNA`.`generator_16` AS
    SELECT
        0 AS `n`
    UNION ALL
    SELECT
        1 AS `1`
    UNION ALL
    SELECT
        2 AS `2`
    UNION ALL
    SELECT
        3 AS `3`
    UNION ALL
    SELECT
        4 AS `4`
    UNION ALL
    SELECT
        5 AS `5`
    UNION ALL
    SELECT
        6 AS `6`
    UNION ALL
    SELECT
        7 AS `7`
    UNION ALL
    SELECT
        8 AS `8`
    UNION ALL
    SELECT
        9 AS `9`
    UNION ALL
    SELECT
        10 AS `10`
    UNION ALL
    SELECT
        11 AS `11`
    UNION ALL
    SELECT
        12 AS `12`
    UNION ALL
    SELECT
        13 AS `13`
    UNION ALL
    SELECT
        14 AS `14`
    UNION ALL
    SELECT
        15 AS `15`;
        
       CREATE OR REPLACE
    ALGORITHM = UNDEFINED VIEW `FORTUNA`.`generator_256` AS
    SELECT
        `hi`.`n` << 4 | `lo`.`n` AS `n`
    FROM
        (
            `FORTUNA`.`generator_16` `lo`
        JOIN `FORTUNA`.`generator_16` `hi`
        );
    
    SELECT
        `Y`.`PeriodEnd` AS `PeriodEnd`,
        `Y`.`BuyerID` AS `BuyerID`,
        CASE `Y`.`RecType` WHEN 'OpenAR' THEN sum(`Y`.`Amount`) OVER (PARTITION BY `Y`.`BuyerID`,`Y`.`RecType` ORDER BY `Y`.`PeriodEnd` ROWS BETWEEN 2 PRECEDING AND 0 FOLLOWING) ELSE 0 END AS `AR_3M`,
        CASE `Y`.`RecType` WHEN 'OpenAR' THEN avg(`Y`.`Amount`) OVER (PARTITION BY `Y`.`BuyerID`,`Y`.`RecType` ORDER BY `Y`.`PeriodEnd` ROWS BETWEEN 2 PRECEDING AND 0 FOLLOWING) ELSE 0 END AS `AR_3M_Avg`,
        CASE `Y`.`RecType` WHEN 'OpenAR' THEN `Y`.`Amount`ELSE 0 END AS `AR_1M`,
        CASE `Y`.`RecType` WHEN 'Revenue' THEN sum(`Y`.`Amount`) OVER ( PARTITION BY `Y`.`BuyerID`, `Y`.`RecType` ORDER BY `Y`.`PeriodEnd` ROWS BETWEEN 2 PRECEDING AND 0 FOLLOWING ) ELSE 0 END AS `Rev_3M`,
        CASE `Y`.`RecType` WHEN 'Revenue' THEN avg(`Y`.`Amount`) OVER (PARTITION BY `Y`.`BuyerID`, `Y`.`RecType` ORDER BY `Y`.`PeriodEnd` ROWS BETWEEN 2 PRECEDING AND 0 FOLLOWING ) ELSE 0 END AS `Rev_3M_Avg`,
        CASE `Y`.`RecType` WHEN 'Revenue' THEN `Y`.`Amount` ELSE 0 END AS `Rev_1M`   
    FROM
    (    SELECT
            `X`.`PeriodEnd` AS `PeriodEnd`,
            `X`.`RecType` AS `RecType`,
            `X`.`BuyerID` AS `BuyerID`,
            sum(`S`.`Amount`) AS `Amount`
        FROM
        (    SELECT last_day( curdate() - INTERVAL `generator_256`.`n` MONTH  ) AS `PeriodEnd`,
                    `b`.`BuyerID` AS `BuyerID`, R.RecType
            FROM `FORTUNA`.`generator_256`
            CROSS JOIN (SELECT DISTINCT `ARSummary`.`BuyerID` AS `BuyerID`
                        FROM `ARSummary`) `b`
            CROSS JOIN (SELECT 'Revenue' AS `RecType`
                        UNION SELECT   'OpenAR' AS `RecType`) AS R
            WHERE `generator_256`.`n` < 18  
        ) as `X`
        LEFT JOIN `ARSummary` `S` ON
            (`X`.`PeriodEnd` = `S`.`PeriodEnd`
                 AND `X`.`RecType` = `S`.`RecType`
                 AND `X`.`BuyerID` = `S`.`BuyerID`
            )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 2023-03-30
      • 1970-01-01
      • 2011-12-30
      • 2021-03-01
      • 2021-08-22
      • 1970-01-01
      相关资源
      最近更新 更多