Если предположить, что вы не можете использовать LAG (например, MSSQL 2008), и что у вас может быть несколько записей для каждой группы продуктов и периода, вы можете использовать следующий запрос.
Пример таблицы и значения:
CREATE TABLE GR (Product_Group VARCHAR(10), Period VARCHAR(6), Amount INT);
INSERT INTO GR VALUES ('Group 1', '201801', 500)
, ('Group 1', '201802', 740)
,('Group 1', '201803', 900)
,('Group 1', '201804', 930)
;
INSERT INTO GR VALUES ('Group 2', '201801', 500)
, ('Group 2', '201803', 800)
,('Group 2', '201803', 1000)
,('Group 2', '201804', 1200)
;
Запрос использует GROUP BY (и CTE для упрощения чтения) для группировки по ProductGroup и Period, а RowNumber для поиска предыдущего значения (если у вас фиксированный период, т.е. если вы хотите показать запись для каждого месяца, когда значение месяца отсутствует Вы можете использовать таблицу Tally Date)
WITH X AS (SELECT Product_Group, Period, SUM(Amount) AS Amount_TOT
, ROW_NUMBER() OVER (PARTITION BY Product_Group ORDER BY PERIOD) AS RN
FROM GR GROUP BY Product_group, Period)
SELECT Product_Group, Period, Amount_TOT, Amount_TOT_PREC, Amount_TOT-ISNULL(Amount_TOT_PREC,0) AS Delta
FROM (SELECT A.Product_Group, A.Period, A.Amount_TOT, B.Amount_TOT AS Amount_TOT_PREC
FROM X A
LEFT JOIN X B ON A.Product_Group=B.Product_Group AND A.RN-1 = B.RN
) C
выход
+---------------+--------+------------+-----------------+-------+
| Product_Group | Period | Amount_TOT | Amount_TOT_PREC | Delta |
+---------------+--------+------------+-----------------+-------+
| Group 1 | 201801 | 500 | NULL | 500 |
| Group 1 | 201802 | 740 | 500 | 240 |
| Group 1 | 201803 | 900 | 740 | 160 |
| Group 1 | 201804 | 930 | 900 | 30 |
| Group 2 | 201801 | 500 | NULL | 500 |
| Group 2 | 201803 | 1800 | 500 | 1300 |
| Group 2 | 201804 | 1200 | 1800 | -600 |
+---------------+--------+------------+-----------------+-------+
Использование LAG (эта функция возвращает значение предыдущей записи, пожалуйста, проверьте документацию Microsoft) быстрее и более читабельно:
WITH X AS (SELECT Product_Group, Period
, SUM(Amount) AS Amount_TOT
FROM GR GROUP BY Product_group, Period)
SELECT Product_Group, Period, Amount_TOT, AMOUNT_PREC
, Amount_TOT-ISNULL(AMOUNT_PREC,0) AS Delta
FROM (SELECT Product_Group, Period, Amount_TOT
, LAG(Amount_TOT) OVER (PARTITION BY Product_Group
ORDER BY PERIOD) AS AMOUNT_PREC
FROM X) A;
То же, что и выше