用于存储和计算历史数据的数据库问题

时间:2009-12-09 21:36:43

标签: mysql database-design stored-procedures cursor

我有一个应用程序可以在不同的时间轮询不同的垃圾箱,并根据重量计算每个垃圾箱中的小部件数量。轮询每隔几分钟完成一次,结果带有时间戳并添加到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

应用程序需要生成“库存历史”报告 - 这将涉及在每个时间步计算什么是总数。在那个时间步的所有箱子里的物品。对于此示例,报告将仅包含下面的timestamp列和CountHistory列(最后一列)(显示其他列只是为了显示计算)

在时间1,A已经被轮询并且有8个小部件。 B和C尚未被调查。所以总数是8。

在时间2,B已经被轮询并且有7个小部件。所以总数是17

在时间3,C已经被轮询并且有4个小部件。所以总数是19

在时间4,A再次轮询,只有一个小部件。所以总数现在是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

对于如何最好地解决这个问题,我将不胜感激。我试图创建一个临时表,使用游标滚动每个记录但无法获得正确的查询。

(之前我曾问过一个相关的问题,但我没有正确地提出这个问题,并且也提到了这个例子。Need Help with queries (views) in Microsoft Access

2 个答案:

答案 0 :(得分:2)

我认为这将满足您的需求。内部查询查找每个时间戳更改每个bin的最新时间戳。

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

答案 1 :(得分:1)

没有实际模型(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