Вопрос базы данных для хранения и вычисления с историческими данными

0

У меня есть приложение, которое проверяет разные ячейки в разное время и вычисляет количество виджетов в каждом ящике на основе веса. Опрос выполняется каждые несколько минут, и результат присваивается 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)

  • 0
    Ты имеешь в виду, что у «Времени 2» всего 15?
  • 0
    Ой, моя вина. Да, во время 2 это только A + B, что составляет 7 + 8 = 15
Теги:
stored-procedures
database-design
cursor

2 ответа

2
Лучший ответ

Я думаю, что это сделает то, что вам нужно. Внутренний запрос находит самую последнюю временную метку, в которой каждый бит был изменен для каждой отметки времени.

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
  • 0
    Работает как шарм! Как раз то, что я искал!
1

Без реальной модели (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
  • 0
    Поскольку количество бинов различается (некоторые виджеты будут в 3 бинах, некоторые - в 4, некоторые - в 10), это может стать проблемой, если я не отформатирую внутренние запросы динамически.
  • 0
    Да, очень верно - я пропустил это в твоем оригинальном посте.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню