sql如何从第2行减去结果行1,从第3行减去结果行2

xurqigkl  于 2021-06-17  发布在  Mysql
关注(0)|答案(3)|浏览(596)

在mysql中,如何从第2行减去第1行,从第3行减去第2行,等等?我从中提取数据的表包含多个产品,所有产品都有多个价格(在不同的日期)
我正在使用的代码:

SELECT 
        orderline_sales.product_name,
        orderline_sales.price
    FROM
        orderline_sales         
    GROUP BY price
    HAVING orderline_sales.product_name = 'Ibuprofen';

我得到的结果是:

|---------------------|------------------|
|      product_name   |     price        |
|---------------------|------------------|
|       Ibuprofen     |      30.20       |
|---------------------|------------------|
|       Ibuprofen     |      32.20       |
|---------------------|------------------|
|       Ibuprofen     |      35.20       |
|---------------------|------------------|

我想要的结果是:

|---------------------|------------------|------------------|
|      product_name   |     price        |   price_change   |
|---------------------|------------------|------------------|
|       Ibuprofen     |      30.20       |         0        |
|---------------------|------------------|------------------|
|       Ibuprofen     |      32.20       |         2        |
|---------------------|------------------|------------------|
|       Ibuprofen     |      35.20       |         3        |
|---------------------|------------------|------------------|
cyvaqqii

cyvaqqii1#

您可能希望查看mysql的用户定义变量,然后您可能希望执行以下操作:

SET @prev := NULL;
SELECT
    DATE(created_at),
    price - COALESCE(@prev, price) AS price_change,
    name,
    (@prev := price) AS price FROM (
        SELECT * FROM items ORDER BY DATE(created_at)
    ) t1
GROUP BY
    name, price, DATE(created_at)
HAVING name = 'Ibuprofen'
ORDER BY DATE(created_at);
Query OK, 0 rows affected (0.00 sec)

我没有检查语法,所以可能有点不对劲,但这是一般的想法。请注意,我添加了日期,以便您可以按它排序,否则结果可能毫无意义。
编辑:
刚刚在我的机器上运行了这个:

SET @prev := NULL;
SELECT
    DATE(created_at),
    price - COALESCE(@prev, price) AS price_change,
    name,
    (@prev := price) AS price FROM (
        SELECT * FROM items ORDER BY DATE(created_at)
    ) t1
GROUP BY
    name, price, DATE(created_at)
HAVING name = 'Ibuprofen'
ORDER BY DATE(created_at);

Query OK, 0 rows affected (0.00 sec)

+------------------+--------------+-----------+-------+
| DATE(created_at) | price_change | name      | price |
+------------------+--------------+-----------+-------+
| 2018-12-10       |            0 | Ibuprofen |   110 |
| 2018-12-13       |          -10 | Ibuprofen |   100 |
| 2018-12-13       |           20 | Ibuprofen |   120 |
+------------------+--------------+-----------+-------+

3 rows in set, 1 warning (0.00 sec)

SELECT * FROM items;
+----+-------+----------------+---------------------+
| id | price | name           | created_at          |
+----+-------+----------------+---------------------+
|  8 |   100 | Ibuprofen      | 2018-12-13 12:52:35 |
|  9 |   110 | Ibuprofen      | 2018-12-10 12:12:12 |
| 10 |   120 | Ibuprofen      | 2018-12-13 12:52:35 |
| 11 |  1000 | Something else | 2018-12-13 13:01:19 |
+----+-------+----------------+---------------------+

4 rows in set (0.00 sec)
q5iwbnjs

q5iwbnjs2#

假设最初的目的是跟踪价格变化(time/id)。假设groupby是用来消除价格不变的行的。你可以做以下(dave答案的变体):

SELECT product_name, price, cast( ifnull(price_change,0) as decimal(6,2)) as price_change
FROM (
SELECT
    product_name,
    price - @prev AS price_change,
    (@prev := price) AS price
FROM
    orderline_sales
    JOIN (SELECT @prev := null) as j
WHERE orderline_sales.product_name = 'Ibuprofen' 
ORDER BY id
) as q
WHERE price_change is null or price_change!=0;

与@dave的答案不同的是去掉了不正确的用法 GROUP BY .
见db小提琴。

dsekswqp

dsekswqp3#

也许这样的办法行得通?

DROP TABLE IF EXISTS test;

CREATE TABLE test (
product_name text,
price numeric
);

INSERT INTO test VALUES 
('ibuprofen', 30.20),
('ibuprofen', 32.20),
('ibuprofen', 35.20);

SELECT DISTINCT t.product_name, t.current_price - t.previous_price AS price_change
FROM (SELECT te.product_name, te.price AS current_price, 
         LAG(te.price) over w  AS previous_price, 
         row_number() over w AS rn
         FROM test AS te 
         WINDOW w AS (ORDER BY te.product_name, te.price)
         ) AS t
WHERE t.product_name = 'ibuprofen'
AND t.rn <> 1
ORDER BY t.product_name, price_change;

此查询返回以下结果:

product_name | price_change 
--------------+--------------
 ibuprofen    |         0.00
 ibuprofen    |         2.00
 ibuprofen    |         3.00

相关问题