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

时间:2018-12-13 20:30:07

标签: mysql calculated-columns correlated-subquery

在MySQL中,如何从第2行减去第1行,从第3行减去第2行,以此类推? 我从中提取数据的表包含多个产品,所有产品都有多个价格(在不同的日期)

我正在使用的代码:

#include <FMX.Platform.Win.hpp>
#include <Winapi.Windows.hpp>

void HideAppOnTaskbar()
{
    HWND hAppWnd = Fmx::Platform::Win::ApplicationHWND();
    ShowWindow(hAppWnd, SW_HIDE);
    LONG_PTR ExStyle = GetWindowLongPtr(hAppWnd, GWL_EXSTYLE);
    SetWindowLongPtr(hAppWnd, GWL_EXSTYLE, (ExStyle & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW);
    //ShowWindow(hAppWnd, SW_SHOW);
}

void ShowAppOnTaskbar()
{
    HWND hAppWnd = Fmx::Platform::Win::ApplicationHWND();
    ShowWindow(hAppWnd, SW_HIDE);
    LONG_PTR ExStyle = GetWindowLongPtr(hAppWnd, GWL_EXSTYLE);
    SetWindowLongPtr(hAppWnd, GWL_EXSTYLE, (ExStyle & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW);
    ShowWindow(hAppWnd, SW_SHOW);
}

void __fastcall TForm1::CreateHandle()
{
    //...
    HideAppOnTaskbar(); // or ShowAppOnTaskbar(), as needed
}

我得到的结果:

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

3 个答案:

答案 0 :(得分:0)

您可能想研究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)

答案 1 :(得分:0)

也许这样的事情可以工作?

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

答案 2 :(得分:0)

让我们假设最初的目的是跟踪价格变化(时间/编号)。假设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