Oracle Analytical函数用于折叠记录

时间:2013-02-04 04:10:57

标签: sql oracle

可以使用分析功能来折叠这些记录 从这个

ssid  start_time            end_time                op_code
65F   08/JAN/2013 14:18:33  08/JAN/2013 14:18:34    2
65F   08/JAN/2013 14:18:53  08/JAN/2013 14:18:54    2
65F   08/JAN/2013 14:18:55  08/JAN/2013 14:18:59    3
65F   08/JAN/2013 14:19:33  08/JAN/2013 14:19:34    2
65F   08/JAN/2013 14:19:53  08/JAN/2013 14:19:54    2
65F   08/JAN/2013 14:19:55  08/JAN/2013 14:19:59    3
72F   08/JAN/2013 14:20:55  08/JAN/2013 14:20:56    2
72F   08/JAN/2013 14:19:57  08/JAN/2013 14:19:59    2

到这个

ssid  start_time            end_time              c_dt                 op_code
65F   08/JAN/2013 14:18:33  08/JAN/2013 14:18:54  08/JAN/2013 14:18:59   2
65F   08/JAN/2013 14:19:33  08/JAN/2013 14:19:54  08/JAN/2013 14:19:59   2
72F   08/JAN/2013 14:19:57  08/JAN/2013 14:20:56

或者我必须仅在for循环中处理它。 我在Oracle 11gR2上

如果下一个op_code是2   然后end_time成为下一条记录的end_time,我们继续更换结束   此记录的时间,直到与op_code 3相同的ssid到达。   当具有op_code 3的记录到达时,我们生成c_dt,它是具有相同ssid但具有op_code 3的记录的end_time。 我们将为下一条记录重新开始此过程

如果我们没有为特定的ssid找到带有op_code 3的记录,那么c_dt将为null 但是end_time将是具有相同ssid的下一条记录的end_time。

希望我对这个棘手的逻辑很清楚

1 个答案:

答案 0 :(得分:2)

我会第一个说这不是很好,但它应该让你朝着正确的方向前进。

首先,创建一个CTE,其中包含具有相应行号的所有记录。

其次,创建另一个CTE,它具有op代码不同的下一条记录。

第三,创建另一个具有最小行号,最大行号和下一行号(可能为空)的CTE,并使用它来获得结果。

很可能会简化,但这是我的第一次尝试。

WITH CTE AS (
  SELECT 
     t.ssid,t.start_time,t.end_time,t.op_code
    ,ROW_NUMBER() OVER (ORDER BY Start_Time) rn
  FROM YourTable t
) , 
CTE2 AS (
  SELECT C.SSID, C.RN, MIN(C2.RN) RN2
  FROM CTE C
    LEFT JOIN CTE C2 ON 
      C.RN < C2.RN AND 
      C.OP_CODE <> C2.OP_CODE AND 
      C.SSID = C2.SSID
  WHERE C.Op_Code = 2
  GROUP BY C.SSID, C.RN
) ,
CTE3 AS (
  SELECT SSID, MIN(RN) MinRN, MAX(RN) MaxRN, RN2 
  FROM CTE2
  GROUP BY SSID, RN2
) 
SELECT c.ssid, 
  c.start_time, 
  c3.end_time, 
  c4.end_time c_dt, 
  c.op_code
FROM CTE c
   JOIN CTE3 c2 ON c.RN = c2.MinRN
   JOIN CTE c3 ON c2.MaxRN = c3.RN
   LEFT JOIN CTE c4 ON c2.RN2 = c4.RN

这是SQL Fiddle

祝你好运。