SQL查询在满足独立条件时随时间累计值

时间:2013-05-28 05:34:42

标签: sql

我有一个应用程序,我需要在符合条件条件的期间内生成(累计)关闭规格产品。最简单的解释方法是举例。

数据存在于一个表 t_data 中,其中包含列:
- tagId(Nvarchar)
- timeStamp(Datetime)
- valueFloat(Float)

要累计的值的tagId是 myVal ,标准值是 myCrit 。当 myCrit 小于10时,我想知道 myVal 的累计值。

tagId    |  timeStamp  |  valueFloat  |  (comment)  
---------+-------------+--------------+--------------   
myCrit   |  08:01:00   |  12.0        |  myCrit starts good - no totalizing yet
myVal    |  08:01:00   |  10.0        |  
myCrit   |  08:02:00   |  9.0         |  myCrit goes bad take next myval as "start"
myVal    |  08:03:00   |  15.0        |  start
myCrit   |  08:04:00   |  8.5         |  
myVal    |  08:05:00   |  16.0        |  
myVal    |  08:06:00   |  20.0        |  end (20-15 totalized)
myCrit   |  08:07:00   |  10.5        |  myCrit is good take prev. myVal as "end"
myVal    |  08:08:00   |  25.0        |  
myCrit   |  08:09:00   |  9.0         |  myCrit bad take next myVal as "start"
myVal    |  08:10:00   |  30.0        |  start
myVal    |  08:11:00   |  40.0        |  end (40-30 totalized)
myCrit   |  08:12:00   |  11.0        |  myCrit good, take prev. myVal as "end"

显示的数据范围查询的累计值应为(20-15 + 40-30)= 15.

总而言之,我想在时间段的开头和结尾添加myVal的差异。段的开始和结束由myCrit的变化标记为好的或坏的值。如何使用存储过程执行此操作?

1 个答案:

答案 0 :(得分:0)

Dang ......好吧,我认为游标应该永远是最后的结果,但根据我在示例数据中看到的,它们可能在这里有意义。这有效:

DO language plpgsql $$
DECLARE mycursor CURSOR FOR SELECT tagId, valueFloat FROM t_data ORDER BY time_stamp;
DECLARE critval float = 10;
DECLARE last_bad boolean = false;
DECLARE gonecritical boolean = false;
DECLARE startval float = -9999;
DECLARE endval float = 0;
DECLARE totalized float = 0;
DECLARE ltagid varchar;
DECLARE lvalue float;
BEGIN
    OPEN mycursor;
    FETCH NEXT from mycursor INTO ltagid, lvalue;
    WHILE (FOUND) LOOP
      /* We have a record */

        /* Are we critical already or not? */
        if gonecritical then
            /* We are already in a critical chunk */
            IF ltagid = 'myVal' and startval = -9999 THEN
                startval = lvalue;
            END IF;
            if ltagid = 'myVal' then
                /* The "last" one we did will always be endval */
                endval = lvalue;
            END IF;
            if ltagid = 'myCrit' and lvalue >= critval then
                /* Yeah! This is the end of critical! */
                totalized = totalized + (endval - startval);
                goneCritical = false;
                startval = -9999;
            END IF;
        else
            /* We are NOT already in a critical chunk */
            if ltagid = 'myCrit' and lvalue < critval then
                /* Yikes we are going critical */
                gonecritical = true;
            END IF;
        end if;

        FETCH NEXT from mycursor INTO ltagid, lvalue;
     END LOOP;
     CLOSE mycursor;
     INSERT INTO t_result select totalized;
END;
 /* totalized has your value! */

$$

我在Postgres中做到了这一点,但是使用了一种非常通用的基于SQL的查询语法,所以你应该能够在MSSQL或任何你需要的地方轻松使用它。

祝你好运! 戴夫