Mysql 从事务表中获取每月增长率

Mysql 从事务表中获取每月增长率,mysql,sql,mysql-5.7,Mysql,Sql,Mysql 5.7,我有这样的交易历史记录: 日期 收入 平衡 2021-05-03 0 1000 2021-05-21 500 1500 2021-05-23 -250 1250 2021-06-02 -500 750 这个计算的逻辑与你的例子不一致 让我们以“月初”和“月底”作为该月第一个日期的记录,以及该月最后一个日期的记录 通过此计算,您确实得到了05月的“0.25”,但对于06月,只有一条记录,因此它是该月的第一条和最后一条记录,计算结果为(750-750)/750,即零 在示例计算中,使用上个月的月末来

我有这样的交易历史记录:

日期 收入 平衡 2021-05-03 0 1000 2021-05-21 500 1500 2021-05-23 -250 1250 2021-06-02 -500 750
这个计算的逻辑与你的例子不一致

让我们以“月初”和“月底”作为该月第一个日期的记录,以及该月最后一个日期的记录

通过此计算,您确实得到了05月的“0.25”,但对于06月,只有一条记录,因此它是该月的第一条和最后一条记录,计算结果为(750-750)/750,即零

在示例计算中,使用上个月的月末来计算第06个月的值,但使用第05个月的月末和年初来计算第05个月的增长。这是两种不同的计算!你得决定用哪一个

如果要使用给定月份中的第一条和最后一条记录(如第05个月),可以使用:

SELECT 
  `t0`.`month`,
  IF(`t1`.balance = 0,
    NULL,
    ((`t2`.balance - `t1`.balance) / `t1`.balance)) AS `growth`
FROM
  (SELECT 
    DATE_FORMAT(`date`, '%Y-%m') AS 'month',
        MIN(`date`) AS 'min_date',
        MAX(`date`) AS 'max_date'
  FROM
    `your_table`
  GROUP BY MONTH(`date`)) AS `t0`
JOIN
  `your_table` AS `t1` ON (`t1`.date = `min_date`)
JOIN
  `your_table` AS `t2` ON (`t2`.date = `max_date`);

请注意“如果”,因为您必须防止被零除-从零到任何正值的增长总是“无限百分比”,这没有意义使用-因此您必须知道在这些情况下您尝试构建的东西应该如何工作。

此计算的逻辑与您的示例不一致

让我们以“月初”和“月底”作为该月第一个日期的记录,以及该月最后一个日期的记录

通过此计算,您确实得到了05月的“0.25”,但对于06月,只有一条记录,因此它是该月的第一条和最后一条记录,计算结果为(750-750)/750,即零

在示例计算中,使用上个月的月末来计算第06个月的值,但使用第05个月的月末和年初来计算第05个月的增长。这是两种不同的计算!你得决定用哪一个

如果要使用给定月份中的第一条和最后一条记录(如第05个月),可以使用:

SELECT 
  `t0`.`month`,
  IF(`t1`.balance = 0,
    NULL,
    ((`t2`.balance - `t1`.balance) / `t1`.balance)) AS `growth`
FROM
  (SELECT 
    DATE_FORMAT(`date`, '%Y-%m') AS 'month',
        MIN(`date`) AS 'min_date',
        MAX(`date`) AS 'max_date'
  FROM
    `your_table`
  GROUP BY MONTH(`date`)) AS `t0`
JOIN
  `your_table` AS `t1` ON (`t1`.date = `min_date`)
JOIN
  `your_table` AS `t2` ON (`t2`.date = `max_date`);

请注意“如果”,因为您必须防止被零除-从零到任何正值的增长总是“无限百分比”,这是没有意义的-因此您必须知道您试图构建的东西在这些情况下应该如何工作。

假设DB版本为
8.0
,然后,您可以在下面的查询中使用分析函数

SELECT month,
       (bal_end - COALESCE(LAG(bal_end) OVER(ORDER BY month), bal_start)) /
       COALESCE(LAG(bal_end) OVER(ORDER BY month), bal_start) AS growth
  FROM (SELECT month,
               MAX(CASE
                     WHEN m_end = 1 THEN
                      sum_balance
                   END) AS bal_end,
               MAX(CASE
                     WHEN m_start = 1 THEN
                      sum_balance
                   END) bal_start
          FROM (SELECT month,
                       SUM(COALESCE(CASE
                                      WHEN bal_start = 1 THEN
                                       balance
                                    END,
                                    0) + COALESCE(revenue, 0)) OVER(ORDER BY date) AS sum_balance,
                       m_end,
                       m_start,
                       date
                  FROM (SELECT DATE_FORMAT(date, '%Y-%m') AS month,
                               t.*,
                               ROW_NUMBER() OVER(PARTITION BY DATE_FORMAT(date, '%Y-%m') ORDER BY date) AS m_start,
                               ROW_NUMBER() OVER(PARTITION BY DATE_FORMAT(date, '%Y-%m') ORDER BY date DESC) AS m_end,
                               ROW_NUMBER() OVER(ORDER BY date) AS bal_start
                          FROM t) AS t0) AS t1
         GROUP BY month) AS t2;
月 生长 2021-05 0.2500 2021-06 -0.4000
如果DB版本为
8.0
,则可以使用以下查询中的分析函数

SELECT month,
       (bal_end - COALESCE(LAG(bal_end) OVER(ORDER BY month), bal_start)) /
       COALESCE(LAG(bal_end) OVER(ORDER BY month), bal_start) AS growth
  FROM (SELECT month,
               MAX(CASE
                     WHEN m_end = 1 THEN
                      sum_balance
                   END) AS bal_end,
               MAX(CASE
                     WHEN m_start = 1 THEN
                      sum_balance
                   END) bal_start
          FROM (SELECT month,
                       SUM(COALESCE(CASE
                                      WHEN bal_start = 1 THEN
                                       balance
                                    END,
                                    0) + COALESCE(revenue, 0)) OVER(ORDER BY date) AS sum_balance,
                       m_end,
                       m_start,
                       date
                  FROM (SELECT DATE_FORMAT(date, '%Y-%m') AS month,
                               t.*,
                               ROW_NUMBER() OVER(PARTITION BY DATE_FORMAT(date, '%Y-%m') ORDER BY date) AS m_start,
                               ROW_NUMBER() OVER(PARTITION BY DATE_FORMAT(date, '%Y-%m') ORDER BY date DESC) AS m_end,
                               ROW_NUMBER() OVER(ORDER BY date) AS bal_start
                          FROM t) AS t0) AS t1
         GROUP BY month) AS t2;
月 生长 2021-05 0.2500 2021-06 -0.4000
你需要从上个月的余额中提取,如果它存在的话。为此,您可以将
lag()
与条件聚合结合起来:

select year(date), month(date),
       (-1 +
        (max(case when seqnum_desc = 1 then balance end) /
         max(case when seqnum_asc = 1 then coalesce(prev_balance, balance) end)
        )
       ) as growth
from (select t.*,
             row_number() over (partition by year(date), month(date) order by date) as seqnum_asc,
             row_number() over (partition by year(date), month(date) order by date desc) as seqnum_desc,
             lag(balance) over (order by date) as prev_balance
      from t
     ) t
group by year(date), month(date);

是一个数字小提琴。

你需要从上个月的余额中提取,如果它存在的话。为此,您可以将
lag()
与条件聚合结合起来:

select year(date), month(date),
       (-1 +
        (max(case when seqnum_desc = 1 then balance end) /
         max(case when seqnum_asc = 1 then coalesce(prev_balance, balance) end)
        )
       ) as growth
from (select t.*,
             row_number() over (partition by year(date), month(date) order by date) as seqnum_asc,
             row_number() over (partition by year(date), month(date) order by date desc) as seqnum_desc,
             lag(balance) over (order by date) as prev_balance
      from t
     ) t
group by year(date), month(date);

是一把小提琴。

@MBauerDC。。。非常感谢。在我使用MYSQL 5.7时,这是一个正确的方向。然而,为了取得最终结果,仍然需要进行一些修改:

SELECT 
  t0.month,
  (t2.balance - (t1.balance - t1.revenue)) / (t1.balance - t1.revenue) AS growth
FROM
  (SELECT 
    DATE_FORMAT(date, '%Y-%m') AS 'month',
        MIN(date) AS 'min_date',
        MAX(date) AS 'max_date'
  FROM
    t
  GROUP BY month) AS t0
JOIN
  t AS t1 ON (t1.date = min_date)
JOIN
  t AS t2 ON (t2.date = max_date)

@姆巴伊尔DC。。。非常感谢。在我使用MYSQL 5.7时,这是一个正确的方向。然而,为了取得最终结果,仍然需要进行一些修改:

SELECT 
  t0.month,
  (t2.balance - (t1.balance - t1.revenue)) / (t1.balance - t1.revenue) AS growth
FROM
  (SELECT 
    DATE_FORMAT(date, '%Y-%m') AS 'month',
        MIN(date) AS 'min_date',
        MAX(date) AS 'max_date'
  FROM
    t
  GROUP BY month) AS t0
JOIN
  t AS t1 ON (t1.date = min_date)
JOIN
  t AS t2 ON (t2.date = max_date)

@巴巴拉斯·奥詹。非常感谢。我回答错了问题。我完全改变了答案。谢谢你的回答。不幸的是,我忘了提到它应该用于MYSQL 5…我的mistake@BarbarosÖzhan。非常感谢。我回答错了问题。我完全改变了答案。谢谢你的回答。不幸的是,我忘了提到它应该是MySQL5的…我的错误你说的选择一个月的第一天的余额或上个月的最后一天的余额是正确的。然而,为了得到当月的初始余额,必须减去第一天的收入。(正如我在另一篇文章中所看到的)你说的选择一个月第一天的余额或上个月最后一天的余额是正确的。然而,为了得到当月的初始余额,必须减去第一天的收入。(在我的另一篇帖子中可以看到)谢谢你的回答。不幸的是,我忘了提到它应该是MYSQL 5的…我的错误you's welcome@Torstenkietz谢谢你的回答。不幸的是,我忘了提到它应该是MYSQL 5的…我的错误You's welcome@TorstenKietz