Другие языки программирования и технологии

[SQL-Access] Как вычесть текущую запись поля из предыдущего?

Пусть в Access имеется такая таблица "Показания счетчиков воды":
Дата Счетчик1 Счетчик2
01.12.12 0 0
01.01.13 100 90
01.02.13 150 130
01.03.13 170 160

Надо узнать, сколько набежало в текущем месяце, т. е. вычесть значение счетчика в текущем месяце из значения счетчика в предыдущем.
Например, Итог1 на 01.02.13 будет равен 170 - 150 = 20.

Дата Итог1 Итог2
01.12.12 0 0
01.01.13 100 90
01.02.13 50 40
01.02.13 20 30
Основная проблема в том, как определить предыдущую запись. Можно, конечно, попробовать получить предыдущую дату с помощью DateAdd:

SELECT Дата, DateAdd("m", -1, Дата) AS Дата_prev FROM [Показания счетчиков воды] ;

Но при этом надо гарантировать, что все соседние даты в таблице различаются ровно на месяц. Лучше воспользоваться тем фактом, что предыдущая дата — это максимальная дата, не превышающая текущую:

SELECT Дата, (SELECT Max(Дата) FROM [Показания счетчиков воды] AS t2 WHERE t2.Дата < t1.Дата) AS Дата_пред FROM [Показания счетчиков воды] AS t1;

Определив предыдущую дату, легко получить значения счетчиков для неё:

SELECT Счетчик1, Счетчик2 FROM [Показания счетчиков воды] WHERE Дата = Дата_пред;

Теперь нужно скомпоновать в один запрос:

SELECT *
FROM (SELECT Дата, Счетчик1, Счетчик2, (SELECT Max(Дата) FROM [Показания счетчиков воды] AS t2 WHERE t2.Дата < t1.Дата) AS Дата_пред FROM [Показания счетчиков воды] AS t1) AS Тек LEFT JOIN [Показания счетчиков воды] AS Пред ON Тек. Дата_пред = Пред. Дата;

LEFT JOIN необходим, чтобы не потерялась первая запись, для которой нет предыдущего значения.

Теперь у нас есть таблица, в каждой записи которой есть данные на текущий и предыдущий месяц. Осталось вычислить требуемое. Надо только решить, что делать с самыми первыми показателями, для которых нет предыдущих. В этом случае, как мне кажется, разумно считать, что предыдущее показание равно текущему, так что итог получится нулевым. В итоге получаем такой запрос:

SELECT Тек. Дата AS Дата, Тек. Счетчик1 - Nz(Пред. Счетчик1,Тек. Счетчик1) AS Итог1, Тек. Счетчик2 - Nz(Пред. Счетчик2,Тек. Счетчик2) AS Итог2
FROM (SELECT Дата, Счетчик1, Счетчик2, (SELECT Max(Дата) FROM [Показания счетчиков воды] AS t2 WHERE t2.Дата < t1.Дата) AS Дата_пред FROM [Показания счетчиков воды] AS t1) AS Тек LEFT JOIN [Показания счетчиков воды] AS Пред ON Тек. Дата_пред = Пред. Дата;
Дима Копылов
Дима Копылов
11 998
Лучший ответ
ГЕНИАЛЬНО!!!! ОГРОМНОЕ СПАСИБО!!!