firebird - 自我加入一张桌子

时间:2013-07-09 10:23:42

标签: sql join firebird self-join

我有一张桌子STARTSTOP

ACTION  DATA                    ID_PPSTARTSTOPPOZ
0   2013-03-18 08:38:00 10451
1   2013-03-18 09:00:00 10453
0   2013-03-18 09:50:00 10466
1   2013-03-18 10:38:00 10467
0   2013-03-19 11:54:00 10499
1   2013-03-19 12:32:00 10505

行动0 - >开始行动 行动1 - >停止行动 DATA是行动的时间戳

我想运行一个select语句,它会返回类似的记录:

ACTION_1   ACTION_2    DURATION
10451        10453       22
10466        10466       48
             ...

一行中所有行动持续时间的OR摘要。

单个数据库查询是否可行? (不创建额外的表格)

3 个答案:

答案 0 :(得分:2)

select A1.ID_PPSTARTSTOPPOZ as Action_0,
       A2.Action_1,
       datediff (minute, A1.DATA ,A2.DATA)

from STARTSTOP A1
JOIN 
(
  select ID_PPSTARTSTOPPOZ as Action_1,
         DATA,
         (select max(ID_PPSTARTSTOPPOZ)
           FROM STARTSTOP 
          where ID_PPSTARTSTOPPOZ<T.ID_PPSTARTSTOPPOZ
                AND
                ACTION=0) AS PREV_ACTION
  from STARTSTOP T
  where ACTION=1 

) A2 on A1.ID_PPSTARTSTOPPOZ=A2.PREV_ACTION

where ACTION = 0
order by A1.ID_PPSTARTSTOPPOZ 

DATEDIFF function

SQLFiddle Example for MSSQL but it has to work under Firebird too

答案 1 :(得分:0)

可以通过单个选择完成,但算法EXECUTE BLOCK可以更快地完成:

EXECUTE BLOCK
  RETURNS (ACTION_1 INTEGER, ACTION_2 INTEGER, DURATION INTEGER)
AS
  DECLARE VARIABLE act INTEGER;
  DECLARE VARIABLE act_id INTEGER;
  DECLARE VARIABLE d TIMESTAMP = NULL;
  DECLARE VARIABLE d1 TIMESTAMP = NULL;
BEGIN
  FOR
    SELECT action, data, id_ppstartstoppoz
    FROM startstop
    ORDER BY data ASC
    INTO :act, :d, :act_id
  DO BEGIN
    IF (:act = 0) THEN
    BEGIN
      d1 = :d;
      action_1 = :act_id;
    END ELSE
    BEGIN
      IF (NOT :d1 IS NULL) THEN
      BEGIN
        action_2 = :act_id;
        duration = DATEDIFF(SECOND, :d1, :d);
        SUSPEND;
        d1 = NULL; 
      END
    END
  END
END

答案 2 :(得分:0)

这可以更简单的方式完成

SELECT TAB1.ID AS ACTION_1,TAB2.ID AS ACTION_2,  
(TAB2.DATA_TS - TAB1.DATA_TS)   MINUTE (4) TO SECOND(6) AS DURATION
FROM 

 (SELECT  ID, DATA_TS , ROW_NUMBER () OVER ( ORDER BY ID )AS RNUM FROM   
 PROCESS WHERE ACTION=0
 )TAB1

 INNER JOIN 

 (SELECT  ID, DATA_TS , ROW_NUMBER () OVER ( ORDER BY ID ) AS RNUM  FROM    
  PROCESS WHERE ACTION=1 
 ) TAB2

 ON ( TAB1.RNUM=TAB2.RNUM)
 ORDER BY 1

  ACTION_1  ACTION_2   DURATION
  10,451    10,453     22:00.000000
  10,466    10,467     48:00.000000
  10,499    10,505     38:00.000000