У меня есть приложение, которое опрашивает разные корзины в разное время и вычисляет количество виджетов в каждой корзине в зависимости от веса. Опрос выполняется каждые несколько минут, а результат помечается меткой времени и добавляется в таблицу MySQL. Таблица содержит 3 колонки ниже. В примере показано 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

Приложению необходимо создать отчет «история запасов» - это потребует вычисления на каждом временном шаге общего количества. элементов из всех ящиков на этом временном шаге. В этом примере отчет будет содержать только столбец с отметкой времени и столбец 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
Soundar Rajan 10 Дек 2009 в 00:36
Вы имеете в виду, что в "At time 2" всего 15?
 – 
Lance Roberts
10 Дек 2009 в 00:44
Ой, моя вина. Да, во время 2 это только A + B, что составляет 7 + 8 = 15
 – 
Soundar Rajan
10 Дек 2009 в 21:05

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
2
Paul 10 Дек 2009 в 01:18
Работает как шарм! Именно то, что я искал!
 – 
Soundar Rajan
10 Дек 2009 в 06:38

Я не уверен, что без реальной модели (DDL) и данных (включая ожидаемый результат) я бы попытался предоставить фактический, проверенный синтаксисом образец SQL. И хотя я думаю, что это было бы легко сделать в коде приложения или с помощью курсора, я думаю, что это можно сделать с помощью одного запроса.

Тем не менее, это будет примерно так - рассмотрим этот 100% псевдокод:

SELECT
 timestamp,
 bin,
 widget_count,
 (SELECT A that is most recent and <= current row's timestamp) A,
 (SELECT B that is most recent and <= current row's timestamp) B,
 (SELECT C that is most recent and <= current row's 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
1
Phil Sandler 10 Дек 2009 в 02:22
Поскольку количество ячеек различается (некоторые виджеты будут в 3 ящиках, некоторые будут в 4, некоторые в 10), это может быть проблемой, если я динамически не форматирую внутренние запросы.
 – 
Soundar Rajan
10 Дек 2009 в 06:40
Да, очень верно - я пропустил это в вашем исходном посте.
 – 
Phil Sandler
10 Дек 2009 в 09:02