A pergunta mudou um pouco, aqui está o meu entendimento atual do que você quer.
CREATE TABLE inventory
(`animal` varchar(6), `date` date, `quantity` int);
INSERT INTO inventory
(`animal`, `date`, `quantity`)
VALUES
('dog', '2015-01-01', 400),
('cat', '2015-01-01', 300),
('dog', '2015-01-02', 402),
('rabbit', '2015-01-01', 500),
('cat', '2015-01-02', 304),
('rabbit', '2015-01-02', 508),
('rabbit', '2015-01-03', 524),
('rabbit', '2015-01-04', 556),
('rabbit', '2015-01-05', 620),
('rabbit', '2015-01-06', 748);
A consulta
select animal,actual_date,past_date,quantity_diff
from
( SELECT a.animal, a.Date
AS actual_date, past_date.Date
AS past_date, (a.quantity - past_date.quantity)
AS quantity_diff,
1 as drewOrder
FROM inventory a
JOIN
(SELECT b.animal, b.date AS date1,
(SELECT MAX(c.date)
FROM inventory c
WHERE c.date < b.date AND c.animal = b.animal
GROUP BY c.animal)
AS date2
FROM inventory b)
AS original_date ON original_date.animal = a.animal
AND original_date.date1 = a.date
JOIN
inventory past_date
ON past_date.animal = a.animal
AND past_date.date = original_date.date2
union
select distinct animal,null,null,null,2 as drewOrder from inventory
) x
order by x.animal,x.drewOrder,x.actual_date;
Os resultados:
+--------+-------------+------------+---------------+
| animal | actual_date | past_date | quantity_diff |
+--------+-------------+------------+---------------+
| cat | 2015-01-02 | 2015-01-01 | 4 |
| cat | NULL | NULL | NULL |
| dog | 2015-01-02 | 2015-01-01 | 2 |
| dog | NULL | NULL | NULL |
| rabbit | 2015-01-02 | 2015-01-01 | 8 |
| rabbit | 2015-01-03 | 2015-01-02 | 16 |
| rabbit | 2015-01-04 | 2015-01-03 | 32 |
| rabbit | 2015-01-05 | 2015-01-04 | 64 |
| rabbit | 2015-01-06 | 2015-01-05 | 128 |
| rabbit | NULL | NULL | NULL |
+--------+-------------+------------+---------------+