简体   繁体   English

如何获取MySQL中连续行之间的差异?

[英]How to get the difference between consecutive rows in MySQL?

I have a table in mysql database this data.

id     date         number   qty
114    07-10-2018    200      5   
120    01-12-2018    300      10
123    03-02-2019    700      12
1126   07-03-2019    1000     15

I want to calculate difference between two consecutive rows and i need output format be like:

id     date         number  diff    qty    avg
114    07-10-2018    200     0       5      0
120    01-12-2018    300     100     10     10
123    03-02-2019    700     400     12     33.33
1126   07-03-2019    1000    300     15     20

Any one know how to do this in mysql query?有谁知道如何在 mysql 查询中做到这一点? I want first value of diff and avg column to be 0 and rest is the difference.我希望 diff 和 avg 列的第一个值为 0,其余的就是差异。

For MySQL 8 then use Lag window function.对于MySQL 8,则使用滞后窗口函数。

SELECT 
    test.id, 
    test.date, 
    test.number, 
    test.qty, 
    IFNULL(test.number - LAG(test.number) OVER w, 0) AS diff,
    ROUND(IFNULL(test.number - LAG(test.number) OVER w, 0)/ test.qty, 2) AS 'Avg'
FROM purchases test
WINDOW w AS (ORDER BY test.`date` ASC);

For MySQL 5.7 or lesser version对于 MySQL 5.7 或更低版本

We can use the MySQL variable to do this job.我们可以使用MySQL 变量来完成这项工作。 Consider your table name is test .考虑您的表名是test

SELECT 
    test.id, 
    test.date, 
    test.number, 
    test.qty, 
    @diff:= IF(@prev_number = 0, 0, test.number - @prev_number) AS diff,
    ROUND(@diff / qty, 2) 'avg',
    @prev_number:= test.number as dummy
FROM 
    test, 
    (SELECT @prev_number:= 0 AS num) AS b
ORDER BY test.`date` ASC;

-------------------------------------------------------------------------------
Output:

| id    | date          | number| qty   | diff  | avg   | dummy | 
-----------------------------------------------------------------
| 114   | 2018-10-07    | 200   | 5     | 0     | 0.00  | 200   |   
| 120   | 2018-12-01    | 300   | 10    | 100   | 10.00 | 300   |   
| 123   | 2019-02-03    | 700   | 12    | 400   | 33.33 | 700   |  
| 1126  | 2019-03-07    | 1000  | 15    | 300   | 20.00 | 1000  |

Explaination:说明:

  • (SELECT @prev_number:= 0 AS num) AS b we initialized variable @prev_number to zero in FROM clause and joined with each row of the test table. (SELECT @prev_number:= 0 AS num) AS b我们在FROM 子句中将变量@prev_number初始化为零,并与测试表的每一行连接。
  • @diff:= IF(@prev_number = 0, 0, test.number - @prev_number) AS diff First we are generating difference and then created another variable diff to reuse it for average calculation. @diff:= IF(@prev_number = 0, 0, test.number - @prev_number) AS diff首先我们生成差异,然后创建另一个变量diff以将其重用于平均值计算。 Also we included one condition to make the diff for first row as zero.我们还包括一个条件,使第一行的差异为零。
  • @prev_number:= test.number as dummy we are setting current number to this variable, so it can be used by next row. @prev_number:= test.number as dummy我们将当前数字设置为这个变量,所以它可以被下一行使用。

Note : We have to use this variable first, in both difference as well as average and then set to the new value, so next row can access value from the previous row.注意:我们必须首先在差值平均值中使用此变量,然后设置为新值,以便下一行可以访问上一行的值。

You can skip/modify order by clause as per your requirements.您可以根据您的要求跳过/修改order by子句。

There could be better ways to do this, but try this:可能有更好的方法来做到这一点,但试试这个:

SELECT A.id,
       A.date,
       A.number,
       A.qty,
       A.diff,
       B.avg
FROM
(SELECT *, abs(LAG(number, 1, number) OVER (ORDER BY id) - number) AS 'diff'
FROM table) AS A
JOIN
(SELECT *, abs(LAG(number, 1, number) OVER (ORDER BY id) - number)/qty AS 'avg' FROM table) AS B
ON A.id = B.id;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM