SQL如何从第2行减去结果第1行,从第3行减去第2行
SQL how to subtract result row 1 from row 2, row 2 from row 3
如何在 MySQL 中从第 2 行减去第 1 行,从第 3 行减去第 2 行等?
我从中提取数据的 table 包含多个产品,所有产品都有多个价格(在不同日期)
我正在使用的代码:
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 |
|---------------------|------------------|------------------|
您可能想查看 MySQL 的 user defined variables,然后您可能想做这样的事情:
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)
也许这样的方法可行?
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;
此查询 returns 以下结果:
product_name | price_change
--------------+--------------
ibuprofen | 0.00
ibuprofen | 2.00
ibuprofen | 3.00
让我们假设最初的目的是跟踪价格变化 (time/id)。假设 GROUP BY 用于消除价格未更改的行。您可以执行以下操作(@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-fiddle。
如何在 MySQL 中从第 2 行减去第 1 行,从第 3 行减去第 2 行等? 我从中提取数据的 table 包含多个产品,所有产品都有多个价格(在不同日期)
我正在使用的代码:
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 |
|---------------------|------------------|------------------|
您可能想查看 MySQL 的 user defined variables,然后您可能想做这样的事情:
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)
也许这样的方法可行?
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;
此查询 returns 以下结果:
product_name | price_change
--------------+--------------
ibuprofen | 0.00
ibuprofen | 2.00
ibuprofen | 3.00
让我们假设最初的目的是跟踪价格变化 (time/id)。假设 GROUP BY 用于消除价格未更改的行。您可以执行以下操作(@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-fiddle。