Reputation: 677
Having a tough time with this. I'm echo'ing this data out in PHP but I figured it would be better to make a query in MySQL.
Here's my table:
My Query (wrong):
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'
Is only retrieving two rows, and the sold_qty is wrong.
The result I am trying to achieve would look like this:
Quantity | timestamp | sold_qty
985 2016-12-27 0
960 2016-12-28 25
955 2016-12-29 5
Can anyone help?
Upvotes: 0
Views: 1059
Reputation: 108460
One option would be use a correlated subquery. This certainly isn't the most efficient approach for large sets, but for a limited number of rows being returned, it's workable.
There appears to be a sequence you want the rows processed and returned, but there is no ORDER BY
clause. From the example data, it looks like it's either ascending by timestamp
column, descending by Quantity
column, and/or ascending by id
. We're just guessing.
Assuming the sequence is by timestamp
and id
, and assuming that the (timestamp,id)
tuple is unique... those are fairly reasonable assumptions, but they are just assumptions, and pretty big ones...
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 ...
For the best shot at adequate performance, we would want a covering index available for the correlated subquery, as an example of a suitable index:
... ON InventoryTest_history (SKU, timestamp, id, quantity)
If the rows should be considered sequenced in an order other than by (timestamp,id)
, the ORDER BY
and the conditions in the WHERE
clause of the subquery need to be modified.
This is just one possible approach. There are other query patterns that will return an equivalent result.
Upvotes: 1
Reputation: 15057
you can also use this without JOIN the table: the out SELECT is only to hide some columns.
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;
sample
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>
Upvotes: 1