【问题标题】:MySQL: How to get the percentage of change of one field compared to a previous oneMySQL:如何获得一个字段与前一个字段相比的变化百分比
【发布时间】:2015-08-07 16:24:22
【问题描述】:

我有一张这样的桌子:

year | revenue | organisation    
2010 | 83863   | asdf    
2011 | 5463    | asdf
2012 | 45345   | asdf
2009 | 32463   | ghjk
2010 | 352667  | ghjk

我需要搜索所有组织的最新收入,到目前为止,我可以构建一个类似的查询

Select new tablename(v.organisation, MAX(v.year), v.revenue) 
from tablename v 
where 1=1 group by v.name

但我还需要了解另一部分,那就是收入与上一年相比的百分比变化。

我怎样才能同时实现这两个功能?最好在一个查询中?

谢谢

【问题讨论】:

    标签: mysql hibernate jpa


    【解决方案1】:

    试试这个:

    SELECT v.organization,
           MAX(v.year) AS currentYear,
           v.revenue,
           ((v.revenue -
               (SELECT i.revenue
                FROM tablename i
                WHERE i.organization = v.organization
                  AND i.year = MAX(v.year) - 1)) /
              (SELECT i.revenue
               FROM tablename i
               WHERE i.organization = v.organization
                 AND i.year = MAX(v.year) - 1) * 100) AS percentDifference
    FROM tablename v
    WHERE 1 = 1
    GROUP BY v.organization,
             v.year;
    

    子选择获取上一年的收入数字,然后执行以下公式:

    ((currentYearRev - lastYearRev)/lastYearRev) * 100
    

    这应该给出百分比差异。我用你的虚拟日期在我的环境中测试了它。

    结果:

    +--------------+-------------+---------+-------------------+
    | organization | currentYear | revenue | percentDifference |
    +--------------+-------------+---------+-------------------+
    | asdf         |        2010 |   83863 |              NULL |
    | asdf         |        2011 |    5463 |          -93.4858 |
    | asdf         |        2012 |   45345 |          730.0384 |
    | ghjk         |        2009 |   32463 |              NULL |
    | ghjk         |        2010 |  352667 |          986.3660 |
    +--------------+-------------+---------+-------------------+
    

    显示当前收入和前几年收入的结果:

    +--------------+-------------+---------+-------------------+---------+
    | organization | currentYear | revenue | percentDifference | lastRev |
    +--------------+-------------+---------+-------------------+---------+
    | asdf         |        2010 |   83863 |              NULL |    NULL |
    | asdf         |        2011 |    5463 |          -93.4858 |   83863 |
    | asdf         |        2012 |   45345 |          730.0384 |    5463 |
    | ghjk         |        2009 |   32463 |              NULL |    NULL |
    | ghjk         |        2010 |  352667 |          986.3660 |   32463 |
    +--------------+-------------+---------+-------------------+---------+
    

    【讨论】:

    • 非常感谢您回答我的问题。但是我注意到我的第一个查询也很糟糕。我需要使用嵌套选择来获取最大年份的行,但还不能解决这个问题,因为在 mysql 上使用对象对我来说是相当新的。
    • 现在它已经准备好了,所以我继续这部分。我遗漏了一个“)”并花了一个小时试图弄清楚为什么它不好。
    • 希望一切顺利。如果是,请接受这个答案。
    • select v.organisation, v.revenue... group by organisation, year - 看起来不对吧?
    • @Strawberry - 这工作完美。我创建了一个数据库和表并对其进行了彻底的测试。你觉得它有什么问题?
    【解决方案2】:

    这是一种方法...

    DROP TABLE IF EXISTS  my_table;
    
    CREATE TABLE my_table
    (year INT NOT NULL
    ,revenue INT NOT NULL
    ,organisation VARCHAR(12) NOT NULL
    ,PRIMARY KEY(year,organisation)
    );
    
    INSERT INTO my_table VALUES
    (2010 ,83863   ,'asdf'),
    (2011 ,5463    ,'asdf'),
    (2012 ,45345   ,'asdf'),
    (2009 ,32463   ,'ghjk'),
    (2010 ,352667  ,'ghjk');
    
    SELECT x.*
          , ((x.revenue - z.revenue)/z.revenue) * 100 pct_diff
       FROM my_table x
       JOIN
          ( SELECT organisation
                 , MAX(year) max_year 
              FROM my_table 
             GROUP 
                BY organisation
          ) y
         ON y.organisation = x.organisation 
        AND y.max_year = x.year
       LEFT
       JOIN my_table z
         ON z.organisation = x.organisation
        AND z.year = x.year - 1;
    
    +------+---------+--------------+----------+
    | year | revenue | organisation | pct_diff |
    +------+---------+--------------+----------+
    | 2010 |  352667 | ghjk         | 986.3660 |
    | 2012 |   45345 | asdf         | 730.0384 |
    +------+---------+--------------+----------+
    

    这是运行历史的一个(慢)版本...

     SELECT x.*
          , ((x.revenue - y.revenue)/y.revenue) * 100 pct_diff
       FROM my_table x
       LEFT
       JOIN my_table y
         ON y.organisation = x.organisation
        AND y.year = x.year - 1
      ORDER 
         BY organisation
          , year;
    

    ...如果有时间我会发布一个更快的替代方案(/记住如何)

    【讨论】:

    • 做得很好。您将如何使用这种方法获得运行历史记录?顺便说一句——我 1 提高了这个。
    • 谢谢。运行历史记录稍有不同,我怀疑它会占用更多内存,因此我可能会想改用 @variables。但我会尝试展示这两种解决方案的示例......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多