日期:2014-05-17  浏览次数:20872 次

关于ORACLE的查询语句
有这样一个设备状态历史表:
序列号ID|设备号|源状态|目标状态|目标状态开始时间|源状态开始时间
001 | A1 | RUN | WAIT |2012-8-1 23:30 |2012-8-1 08:30 |  
002 | A1 | WAIT | IDLE |2012-8-2 10:30 |2012-8-1 23:30 | 
003 | A1 | IDLE | RUN |2012-8-2 19:30 |2012-8-2 10:30 | 
004 | A1 | RUN | IDLE |2012-8-3 12:30 |2012-8-2 19:30 |
005 | A2 | RUN | WAIT |2012-8-1 20:30 |2012-8-1 08:30 |  
006 | A2 | WAIT | IDLE |2012-8-2 11:30 |2012-8-1 20:30 | 
007 | A2 | IDLE | RUN |2012-8-2 18:30 |2012-8-2 11:30 | 
008 | A2 | RUN | IDLE |2012-8-3 12:30 |2012-8-2 18:30 |

这个表的作用是这样,当一个设备的状态改变时,就会在这个表里面插入一条数据,
记录一下这个设备由什么状态改为什么状态。
其中表的“源状态开始时间”是等于对应的设备的上一个状态的“目标状态开始时间”

我的困难是:
现在需要查询:用户输入一段时间,例:2012-8-2 00:00至2012-9-4 00:00
在这段时间内,各个设备处在每一种状态下的时长。

难点:像A1这台设备,
最后的状态(目标状态)是IDLE,
这样状态的开始时间(目标状态开始时间)是:2012-8-3 12:30
也就是说A1这个设备从2012-8-3 12:30到现在都是处于IDLE状态。
那么A1处于IDLE状态的时间就应该是历史内统计的时间再加上从2012-8-3 12:30到现在的时间。

我怎么去组织这样的查询语句?

请高手指点迷津。


------解决方案--------------------
SQL code

--给你补了一条数据进去,条件让我改成8月1日0点了,不然看着怪怪的。
[SYS@myoracle] SQL>WITH T AS
  2   (SELECT '001' ID,
  3           'A1' NAME,
  4           'RUN ' F_STATUS,
  5           'WAIT' T_STATUS,
  6           TO_DATE('2012-8-1 23:30', 'yyyy-mm-dd hh24:mi') T_TIME,
  7           TO_DATE('2012-8-1 08:30', 'yyyy-mm-dd hh24:mi') F_TIME
  8      FROM DUAL
  9    UNION ALL
 10    SELECT '002' ID,
 11           'A1' NAME,
 12           'WAIT' F_STATUS,
 13           'IDLE' T_STATUS,
 14           TO_DATE('2012-8-2 10:30', 'yyyy-mm-dd hh24:mi') T_TIME,
 15           TO_DATE('2012-8-1 23:30', 'yyyy-mm-dd hh24:mi') F_TIME
 16      FROM DUAL
 17    UNION ALL
 18    SELECT '003' ID,
 19           'A1' NAME,
 20           'IDLE' F_STATUS,
 21           'RUN ' T_STATUS,
 22           TO_DATE('2012-8-2 19:30', 'yyyy-mm-dd hh24:mi') T_TIME,
 23           TO_DATE('2012-8-2 10:30', 'yyyy-mm-dd hh24:mi') F_TIME
 24      FROM DUAL
 25    UNION ALL
 26    SELECT '004' ID,
 27           'A1' NAME,
 28           'RUN ' F_STATUS,
 29           'IDLE' T_STATUS,
 30           TO_DATE('2012-8-3 12:30', 'yyyy-mm-dd hh24:mi') T_TIME,
 31           TO_DATE('2012-8-2 19:30', 'yyyy-mm-dd hh24:mi') F_TIME
 32      FROM DUAL
 33    UNION ALL
 34    SELECT '005' ID,
 35           'A2' NAME,
 36           'RUN ' F_STATUS,
 37           'WAIT' T_STATUS,
 38           TO_DATE('2012-8-1 20:30', 'yyyy-mm-dd hh24:mi') T_TIME,
 39           TO_DATE('2012-8-1 08:30', 'yyyy-mm-dd hh24:mi') F_TIME
 40      FROM DUAL
 41    UNION ALL
 42    SELECT '006' ID,
 43           'A2' NAME,
 44           'WAIT' F_STATUS,
 45           'IDLE' T_STATUS,
 46           TO_DATE('2012-8-2 11:30', 'yyyy-mm-dd hh24:mi') T_TIME,
 47           TO_DATE('2012-8-1 20:30', 'yyyy-mm-dd hh24:mi') F_TIME
 48      FROM DUAL
 49    UNION ALL
 50    SELECT '007' ID,
 51           'A2' NAME,
 52           'IDLE' F_STATUS,
 53           'RUN ' T_STATUS,
 54           TO_DATE('2012-8-2 18:30', 'yyyy-mm-dd hh24:mi') T_TIME,
 55           TO_DATE('2012-8-2 11:30', 'yyyy-mm-dd hh24:mi') F_TIME
 56      FROM DUAL
 57    UNION ALL
 58    SELECT '008' ID,
 59           'A2' NAME,
 60           'RUN ' F_STATUS,
 61           'IDLE' T_STATUS,
 62           TO_DATE('2012-8-3 12:30', 'yyyy-mm-dd hh24:mi') T_TIME,
 63           TO_DATE('2012-8-2 18:30', 'yyyy-mm-dd hh24:mi') F_TIME
 64      FROM DUAL),
 65  T2 AS
 66   (SELECT ID, NAME, F_STATUS, T_STATUS, F_TIME, T_TIME
 67      FROM T
 68    UNION
 69    SELECT TRIM(TO_CHAR(ID + 1, '099')), NAME, T_STATUS, '-', T_TIME, SYSDATE
 70      FROM T
 71     WHERE CONNECT_BY_ISLEAF = 1
 72    CONNECT BY NOCYCLE PRIOR NAME = NAME
 73           AND PRIOR T_TIME = F_TIME)
 74  SELECT NAME, F_STATUS, SUM(T_TIME - F_TIME)
 75    FROM T2
 76   WHERE F_TIME BETWEEN TO