Mysql 计算上一行值的增加/减少百分比

Mysql 计算上一行值的增加/减少百分比,mysql,sql,Mysql,Sql,我有一张像这样的桌子: |date_start | date_end |amount | +------------+-------------+-------+ |2015-02-23 | 2015-03-01 |50 | |2015-03-02 | 2015-03-08 |50 | |2015-03-09 | 2015-03-15 |100 | |2015-03-16 | 2015-03-22 |800 | |2015-03-23 |

我有一张像这样的桌子:

|date_start  | date_end    |amount | 
+------------+-------------+-------+
|2015-02-23  | 2015-03-01  |50     |
|2015-03-02  | 2015-03-08  |50     |
|2015-03-09  | 2015-03-15  |100    |
|2015-03-16  | 2015-03-22  |800    |
|2015-03-23  | 2015-03-29  |50     |
SELECT m.date_start AS mStart, mt.date_start AS mtStart
FROM myTable m
JOIN myTable mT ON m.date_start < mt.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start);
SELECT 
  mT.date_start AS secondDate, 
  mT.amount - m.amount AS percentChange
FROM myTable m
JOIN myTable mT ON m.date_start < mT.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start);
我想计算一下从上一个日期起,列金额的增减百分比。比如结果会是这样的

|date_start  | date_end    |amount | perc_change | 
+------------+-------------+-------+-------------+
|2015-02-23  | 2015-03-01  |50     | 
|2015-03-02  | 2015-03-08  |50     | 0
|2015-03-09  | 2015-03-15  |100    | 50
|2015-03-16  | 2015-03-22  |800    | 700
|2015-03-23  | 2015-03-29  |50     | -750

我已经找了好几天,绞尽脑汁了。通常,我只是使用服务器端代码来实现这一点,但现在我需要将其全部包含在查询中。

看起来是这样的,我没有环境来测试此选择,但我认为它应该可以工作

    SELECT t1.date_start, t1.date_end, t1.amount, (t1.amount - t2.amount)  as  perc_change
    FROM table1 t1 
      JOIN table1 t2  ON t1.id = t2.id + 1 // here your join to 
   //get next row and calculate this perc_change field

如果我们假设前一行总是在当前行开始前一天结束,就像在示例数据中一样,那么您可以使用联接。增加的百分比为:

select t.*,
       100 * (t.amount - tprev.amount) / tprev.amount
from atable t left join
     atable tprev
     on tprev.date_end = t.date_start - interval 1 day;
但是,您的结果似乎只是有差异,这更容易计算:

select t.*,
       (t.amount - tprev.amount) as diff
from atable t left join
     atable tprev
     on tprev.date_end = t.date_start - interval 1 day;

我首先将表中的每一行与其后的一行连接起来,如下所示:

|date_start  | date_end    |amount | 
+------------+-------------+-------+
|2015-02-23  | 2015-03-01  |50     |
|2015-03-02  | 2015-03-08  |50     |
|2015-03-09  | 2015-03-15  |100    |
|2015-03-16  | 2015-03-22  |800    |
|2015-03-23  | 2015-03-29  |50     |
SELECT m.date_start AS mStart, mt.date_start AS mtStart
FROM myTable m
JOIN myTable mT ON m.date_start < mt.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start);
SELECT 
  mT.date_start AS secondDate, 
  mT.amount - m.amount AS percentChange
FROM myTable m
JOIN myTable mT ON m.date_start < mT.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start);
这将连接表,以便在有以下日期的情况下可以看到每一行。如果没有,则不会返回日期

获得这些值后,可以调整SELECT查询以显示与之前日期相比的百分比变化,如下所示:

|date_start  | date_end    |amount | 
+------------+-------------+-------+
|2015-02-23  | 2015-03-01  |50     |
|2015-03-02  | 2015-03-08  |50     |
|2015-03-09  | 2015-03-15  |100    |
|2015-03-16  | 2015-03-22  |800    |
|2015-03-23  | 2015-03-29  |50     |
SELECT m.date_start AS mStart, mt.date_start AS mtStart
FROM myTable m
JOIN myTable mT ON m.date_start < mt.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start);
SELECT 
  mT.date_start AS secondDate, 
  mT.amount - m.amount AS percentChange
FROM myTable m
JOIN myTable mT ON m.date_start < mT.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start);
我想在此指出,当你在问题中说“百分比差异”时,你的预期结果与百分比无关,而只是价值差异。如果您需要以不同的方式进行计算,您可以调整上面的select查询以满足您的需要

最后要做的事情是将它连接回原始表,以便一起查看所有值。为了能够看到表的第一个日期,必须使用左连接来完成此操作。最后一个问题是:

SELECT m.date_start, m.date_end, m.amount, tmp.percentChange
FROM myTable m
LEFT JOIN(
  SELECT 
    mT.date_start AS secondDate, 
    mT.amount - m.amount AS percentChange
  FROM myTable m
  JOIN myTable mT ON m.date_start < mT.date_start AND mt.date_start = (SELECT MIN(date_start) FROM myTable WHERE date_start > m.date_start)
) tmp ON tmp.secondDate = m.date_start;
下面是一个例子。

试试这个:

 SELECT t.*,
 amount - (SELECT amount FROM transactions prev WHERE prev.date_end     < t.date_start ORDER BY date_start DESC LIMIT 1) AS changes
 FROM   transactions t

您可以使用mysql var系统:

SELECT date_start, date_end, IF(@last IS NOT NULL,ammount - @last , '' ) as perc_change, @last := amount as amount 
From table 
ORDER BY date_start; 

var@last在每篇文章中都设置了,因此perc_change和amount之间的列顺序很重要

您可以创建吗,我在sql server中做了类似的操作,我想我可以调整它以适应此情况……您确定要计算百分比变化吗?50到100是100%的变化,100到800是800%的变化…这是sql fiddle表,得到了这个错误消息。。。字段列表中的“date_start”列模糊不清这不能保证产生正确的结果:涉及用户变量的表达式的求值顺序未定义,注意日期相隔一天!如果这是一致的,那么查询就容易多了。McAdam在SQL Fiddle上工作,但是当通过MySQL执行时,为什么会收到错误消息。。。“on子句”中的未知列“mt.date\u start”?@user3768071您可能在其中一个表别名上打错了字。仔细检查。这是我第一次想到的,所以我复制了你的精确表和查询,没有做任何更改,我得到了一个非常奇怪的错误。我敢打赌,我们中的一个人刚刚在某个地方打错了字。你确定你使用的是tmp.secondDate=m.date\u start,而不是mt吗?@user3768071我认为MySQL不区分大小写,但请注意,在我的查询中,我将别名设置为mt,但有一点是小写的mt?尝试更改它,看看它是否运行。