SQL как вычесть результат строки 1 из строки 2, строки 2 из строки 3 - PullRequest
0 голосов
/ 13 декабря 2018

Как вычесть строку 1 из строки 2 и строку 2 из строки 3 и т. Д. В MySQL?Таблица, из которой я извлекаю свои данные, содержит несколько продуктов, и все продукты имеют несколько цен (на разные даты)

Код, с которым я работаю:

 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        |
|---------------------|------------------|------------------|

Ответы [ 3 ]

0 голосов
/ 14 декабря 2018

Может быть, что-то подобное может работать?

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
0 голосов
/ 14 декабря 2018

Предположим, что первоначальной целью было отслеживать изменения цены (время / идентификатор).Предполагая, что 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-скрипка .

0 голосов
/ 13 декабря 2018

Возможно, вы захотите взглянуть на определяемые пользователем переменные 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)
...