对此感到困难。我在PHP中回应这些数据,但我认为在MySQL中进行查询会更好。
这是我的表:
我的查询(错误):
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是错误的。
我想要达到的结果如下:
Quantity | timestamp | sold_qty
985 2016-12-27 0
960 2016-12-28 25
955 2016-12-29 5
有人可以帮忙吗?
答案 0 :(得分:1)
一个选项是使用相关子查询。对于大型集合来说,这当然不是最有效的方法,但是对于返回的有限行数,它是可行的。
似乎有一个序列需要处理和返回行,但没有ORDER BY
子句。从示例数据看,它似乎是按timestamp
列升序,按Quantity
列降序,和/或按id
递增。我们只是在猜测。
假设序列是timestamp
和id
,并假设(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>