У меня есть приложение, которое проверяет разные ячейки в разное время и вычисляет количество виджетов в каждом ящике на основе веса. Опрос выполняется каждые несколько минут, и результат присваивается timestamped и добавляется в таблицу MySQL. Таблица содержит три столбца ниже. В примере показаны 3 ячейки (A, B и C), но для одного и того же виджета может быть от 1 до 10 бункеров. (Крошечные виджеты могут быть только в 1 или 2 бункерах, а большие виджеты могут занимать больше бункеров)
timestamp bin Widget_Count
--------------------------
1 A 8
2 B 7
3 C 4
4 A 1
5 B 3
6 C 5
7 A 6
8 B 7
9 C 2
Приложению необходимо создать отчет "История запасов" - это будет включать в себя вычисления на каждом временном интервале, каков общий нет. элементов из всех бункеров в тот момент времени. В этом примере отчет будет содержать только столбец timestamp и столбец CountHistory (последний столбец) ниже (другие столбцы показаны только для отображения вычислений)
В момент 1 A был опрошен и имеет 8 виджетов. B и C не были опрошены. Таким образом, общее число равно 8.
В момент 2 B был опрошен и имеет 7 виджетов. Таким образом, сумма составляет 17
В момент 3 C был опрошен и имеет 4 виджета. Таким образом, общее значение составляет 19
В момент 4, A снова опрошено и имеет только 1 виджет. Таким образом, сумма теперь равна 1 + 4 + 7 = 12
.. и т.д.
timestamp bin Widget_ A B C CountHistory
Count (stock flow)
--------------------------------------------------------
1 A 8 8 0 0 8
2 B 7 8 7 0 15
3 C 4 8 7 4 19
4 A 1 1 7 4 12
5 B 3 1 3 4 8
6 C 5 1 3 5 9
7 A 6 6 3 5 14
8 B 7 6 7 5 18
9 C 2 6 7 2 15
Я был бы признателен за любую помощь в том, как лучше всего это сделать. Я попытался создать временную таблицу, прокручивая каждую запись с помощью курсора, но не смог получить правильные запросы.
(Я задал связанный с ним вопрос раньше, но я не правильно сформулировал вопрос и придумал пример. Нужна помощь с запросами (представлениями) в Microsoft Access)
Я думаю, что это сделает то, что вам нужно. Внутренний запрос находит самую последнюю временную метку, в которой каждый бит был изменен для каждой отметки времени.
SELECT m.timestamp, SUM(w.Widget_Count) AS CountHistory
FROM (
SELECT a.timestamp, b.bin, MAX(b.timestamp) AS intMostRecentTimestamp
FROM WidgetTable a
CROSS JOIN WidgetTable b
WHERE a.timestamp >= b.timestamp
GROUP BY a.timestamp, b.bin, a.Widget_Count
) m
INNER JOIN WidgetTable w ON m.intMostRecentTimestamp = w.timestamp
GROUP BY m.timestamp
ORDER BY m.timestamp
Без реальной модели (DDL) и данных (включая ожидаемый результат) я не уверен, что попытаюсь предоставить фактический, проверенный синтаксисом образец SQL. И хотя я думаю, что это было бы легко сделать в коде приложения или с помощью курсора, я думаю, что это можно сделать в одном запросе.
Тем не менее, это будет примерно так: рассмотрите этот 100% псевдокод:
SELECT
timestamp,
bin,
widget_count,
(SELECT A that is most recent and <= current row timestamp) A,
(SELECT B that is most recent and <= current row timestamp) B,
(SELECT C that is most recent and <= current row timestamp) C,
(SELECT sum of last three columns) CountHistory
FROM
widget_bin_table
Возможно, это можно сделать с помощью объединений вместо подзапросов, и объединения будут более эффективными. Но у вас есть идея.
Править: хорошо, вопрос заставил мозг кровоточить, и я не мог отдохнуть, пока не решил его до моего удовлетворения. Затем я вернулся, чтобы опубликовать обновление, и Пол уже ответил с более элегантным решением.:)
Вот мое решение с рабочим SQL (с использованием SQL Server) в случае, если кто-то заботится:
SELECT
timestamp, bin, widget_count, A, B, C, A + B + C CountHistory
FROM
(
SELECT
wb.timestamp,
wb.bin,
wb.widget_count,
ISNULL((SELECT TOP 1 widget_count FROM widget_bin wb1 WHERE wb1.bin = 'A'
AND wb1.timestamp <= wb.timestamp ORDER BY wb1.timestamp DESC), 0) A,
ISNULL((SELECT TOP 1 widget_count FROM widget_bin wb1 WHERE wb1.bin = 'B'
AND wb1.timestamp <= wb.timestamp ORDER BY wb1.timestamp DESC), 0) B,
ISNULL((SELECT TOP 1 widget_count FROM widget_bin wb1 WHERE wb1.bin = 'C'
AND wb1.timestamp <= wb.timestamp ORDER BY wb1.timestamp DESC), 0) C
FROM
widget_bin wb
) sub