Вы можете попробовать что-то вроде следующего:
SELECT CONCAT(YEAR(s1.date), '-', MONTH(s1.date)) month,
s1.person,
s2.total_sales sales_total,
s1.sales - s3.sales gain_loss
FROM sales s1
JOIN (
SELECT person, SUM(sales) total_sales FROM sales GROUP BY person
) s2 ON (s2.person = s1.person)
LEFT JOIN sales s3 ON
(s3.date = DATE_SUB(s1.date, INTERVAL 1 MONTH) AND s3.person = s1.person)
WHERE s1.date = STR_TO_DATE(CONCAT('01-', MONTH(NOW()), '-', YEAR(NOW())), '%d-%m-%Y')
GROUP BY s1.person, s1.date
ORDER BY s1.person, s1.date;
Часть предложения WHERE
, где s1.date = STR_TO_DATE(...)
в основном ограничивает s1.date
текущим месяцем и годом. У меня есть ощущение, что есть более точное решение, но сейчас я не могу придумать подходящую альтернативу.
Контрольный пример:
CREATE TABLE sales (id int, date date, person varchar(40), sales int);
INSERT INTO SALES VALUES (1, '2010-9-01', 'Alice', 5);
INSERT INTO SALES VALUES (2, '2010-8-01', 'Alice', 2);
INSERT INTO SALES VALUES (3, '2010-9-01', 'Peter', 2);
INSERT INTO SALES VALUES (4, '2010-8-01', 'Peter', 3);
INSERT INTO SALES VALUES (5, '2010-9-01', 'Bob', 5);
INSERT INTO SALES VALUES (6, '2010-8-01', 'Bob', 7);
Результат:
+--------+--------+-------------+-----------+
| month | person | sales_total | gain_loss |
+--------+--------+-------------+-----------+
| 2010-9 | Alice | 7 | 3 |
| 2010-9 | Bob | 12 | -2 |
| 2010-9 | Peter | 5 | -1 |
+--------+--------+-------------+-----------+
3 rows in set (0.00 sec)