从上一行MySQL中减去数量

时间:2016-12-29 17:15:33

标签: mysql

对此感到困难。我在PHP中回应这些数据,但我认为在MySQL中进行查询会更好。

这是我的表:

view the source on Github

我的查询(错误):

SELECT i1.Quantity,
i1.timestamp,
(i2.Quantity - i1.Quantity) as sold_qty 
FROM InventoryTest_history i1
INNER JOIN
InventoryTest_history i2 ON i2.id = i1.id + 1
WHERE i1.SKU = '(L) U-Joint'

只检索两行,而sold_qty是错误的。

enter image description here

我想要达到的结果如下:

Quantity |  timestamp   | sold_qty
985         2016-12-27      0  
960         2016-12-28      25
955         2016-12-29      5

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

一个选项是使用相关子查询。对于大型集合来说,这当然不是最有效的方法,但是对于返回的有限行数,它是可行的。

似乎有一个序列需要处理和返回行,但没有ORDER BY子句。从示例数据看,它似乎是按timestamp列升序,按Quantity列降序,和/或按id递增。我们只是在猜测。

假设序列是timestampid,并假设(timestamp,id)元组是唯一的......那些是相当合理的假设,但它们只是假设,而且非常大的...

SELECT ih.Quantity
     , ih.timestamp

     , IFNULL(
                 ( SELECT pr.Quantity
                     FROM InventoryTest_history pr
                    WHERE pr.SKU = ih.SKU
                      AND pr.timestamp <= ih.timestamp
                      AND (pr.timestamp < ih.timestamp OR pr.id < ih.id )
                    ORDER BY pr.SKU DESC, pr.timestamp DESC, pr.id DESC
                    LIMIT 1
                 )
                 - ih.Quantity
       ,0) AS sold_qty

  FROM InventoryTest_history ih
 WHERE ih.SKU = '(L) U-Joint'
 ORDER BY ... 

为了获得足够性能的最佳镜头,我们希望相关子查询可以使用覆盖索引,作为合适索引的示例:

 ... ON InventoryTest_history (SKU, timestamp, id, quantity) 

如果应该按照除(timestamp,id)以外的顺序对行进行排序,则需要修改ORDER BY和子查询的WHERE子句中的条件。

这只是一种可能的方法。还有其他查询模式将返回相同的结果。

答案 1 :(得分:1)

你也可以在没有JOIN表的情况下使用它:out SELECT只是为了隐藏一些列。

SELECT Quantity, `timestamp`, sold_qty
FROM (
    SELECT i.*,
    @sold_qty := GREATEST(@last_qty - i.`Quantity`,0) as sold_qty,
    @last_qty := i.`Quantity` as last_qty
    FROM InventoryTest_history i
    CROSS JOIN ( SELECT @last_qty := '', @sold_qty := 0) as init
    ORDER BY `timestamp`
    ) as result;

<强>样品

mysql> SELECT * from InventoryTest_history;

+----+-------------+----------+---------------------+
| id | SKU         | Quantity | timestamp           |
+----+-------------+----------+---------------------+
|  1 | (L) U-Joint |      985 | 2016-12-27 10:08:58 |
|  2 | (L) U-Joint |      960 | 2016-12-28 10:09:52 |
|  3 | (L) U-Joint |      955 | 2016-12-29 16:01:02 |
+----+-------------+----------+---------------------+
3 rows in set (0,02 sec)

mysql> SELECT Quantity, `timestamp`, sold_qty
    -> FROM (
    ->     SELECT i.*,
    ->     @sold_qty := GREATEST(@last_qty - i.`Quantity`,0) as sold_qty,
    ->     @last_qty := i.`Quantity` as last_qty
    ->     FROM InventoryTest_history i
    ->     CROSS JOIN ( SELECT @last_qty := '', @sold_qty := 0) as init
    ->     ORDER BY `timestamp`
    ->     ) as result;
+----------+---------------------+----------+
| Quantity | timestamp           | sold_qty |
+----------+---------------------+----------+
|      985 | 2016-12-27 10:08:58 |        0 |
|      960 | 2016-12-28 10:09:52 |       25 |
|      955 | 2016-12-29 16:01:02 |        5 |
+----------+---------------------+----------+
3 rows in set (0,00 sec)

mysql> SELECT i.*,
    -> @sold_qty := GREATEST(@last_qty - i.`Quantity`,0) as sold_qty,
    -> @last_qty := i.`Quantity` as last_qty
    -> FROM InventoryTest_history i
    -> CROSS JOIN ( SELECT @last_qty := '', @sold_qty := 0) as init
    -> ORDER BY `timestamp`;
+----+-------------+----------+---------------------+----------+----------+
| id | SKU         | Quantity | timestamp           | sold_qty | last_qty |
+----+-------------+----------+---------------------+----------+----------+
|  1 | (L) U-Joint |      985 | 2016-12-27 10:08:58 |        0 |      985 |
|  2 | (L) U-Joint |      960 | 2016-12-28 10:09:52 |       25 |      960 |
|  3 | (L) U-Joint |      955 | 2016-12-29 16:01:02 |        5 |      955 |
+----+-------------+----------+---------------------+----------+----------+
3 rows in set (0,00 sec)

mysql>