计算连续行的时间差

时间:2015-06-29 13:50:37

标签: sql sql-server

根据我的下列要求,有人可以帮我处理SQL查询吗? 我有一张这样的桌子。

S_ID      S_ACTV_CODE   S_USER  S_DATETIME            S_ACT_IND
AAA-111   NULL          USER1   2015-06-15 00:21:06   0
AAA-111   2             USER1   2015-06-15 00:21:07   0
AAA-111   2             USER1   2015-06-15 00:25:12   0
AAA-111   4             USER2   2015-06-17 03:20:33   0
AAA-111   3             USER1   2015-06-17 03:43:25   0
AAA-111   4             USER3   2015-06-22 05:02:37   0
AAA-111   4             USER4   2015-06-23 05:25:05   1
AAA-112   NULL          USER4   2015-06-25 11:11:11   0
AAA-112   4             USER3   2015-06-25 11:11:12   0
AAA-112   4             USER4   2015-06-26 20:25:49   0
AAA-112   4             USER2   2015-06-29 18:04:32   1
AAA-113   NULL          USER2   2015-06-24 07:10:37   0
AAA-113   NULL          USER1   2015-06-24 07:10:41   0
AAA-113   3             USER1   2015-06-24 07:10:43   1

基本上我想计算S_Users在特定S_ACTV_CODE上花费的时间:

  • S_ACTV_CODE_PREV表示先前的有效记录。
  • S_START_TIME是S_ACTV_CODE启动时S_DATETIME的时间
  • S_END_TIME是S_ACTV_CODE更改为另一个S_ACTV_CODE之前的时间
  • 对于第一条记录,S_ACTV_CODE为空,因此没有S_ACTV_CODE_PREV,因此S_ACTV_CODE_PREV为NULL
  • 对于第二条记录,S_ACTV_CODE有一些值,但第一条记录的S_ACTV_CODE_PREV为NULL。所以第二条记录 S_ACTV_CODE_PREV也是NULL
  • 对于最后一条记录(表示S_ACTV_IND = 1),用户当前正在处理它并且S_ACTV_CODE未更改。所以S_END_TIME是开放的 时间,我们希望将其保持为NULL

所以结果如下:

S_ID      S_ACTV_CODE_PREV  S_ACTV_CODE_CURR  S_USER  S_START_TIME         S_END_TIME             TIME_SPENT (in Sec)
AAA-111   NULL              NULL              USER1   2015-06-15 00:21:06  2015-06-15 00:21:07    1
AAA-111   NULL              2                 USER1   2015-06-15 00:21:07  2015-06-17 03:20:33    183566
AAA-111   2                 4                 USER2   2015-06-17 03:20:33  2015-06-17 03:43:25    1372
AAA-111   4                 3                 USER3   2015-06-17 03:43:25  2015-06-22 05:02:37    436752
AAA-111   3                 4                 USER4   2015-06-22 05:02:37  NULL                   NULL
AAA-112   NULL              NULL              USER4   2015-06-25 11:11:11  2015-06-25 11:11:12    1
AAA-112   NULL              4                 USER3   2015-06-25 11:11:12  NULL                   NULL
AAA-113   NULL              NULL              USER2   2015-06-24 07:10:37  2015-06-24 07:10:43    6
AAA-113   NULL              3                 USER1   2015-06-24 07:10:43  NULL                   NULL

2 个答案:

答案 0 :(得分:3)

重新编写SQL以获取行的第一个日期和最后一个用户。这让它变得更加难看,但这应该有效:

select
  s_id,
  lag(s_actv_code, 1) over (partition by s_id order by s_datetime asc) as s_actv_code_prev,
  s_actv_code,
  s_user,
  s_datetime as start_time,
  lead(s_datetime, 1) over (partition by s_id order by s_datetime asc) as end_time,
  datediff (second, s_datetime,
    lead(s_datetime, 1) over (partition by s_id order by s_datetime asc)) as duration 
from
(
  select distinct
  s_id,
  S_ACTV_CODE,
  last_value(s_user)
  over (partition by s_id, S_ACTV_CODE, GRP 
        order by S_datetime asc
        rows between current row and unbounded following) as s_user,
  first_value(s_datetime)
  over (partition by s_id, S_ACTV_CODE, GRP 
        order by S_datetime asc
        ROWS UNBOUNDED PRECEDING
      ) as s_datetime
   from (
     select
       *,
       row_number() over (partition by s_id order by s_datetime asc) -
       row_number() over (partition by s_id, s_actv_code order by s_datetime asc) as GRP
     from
       table1
   ) X
) Y
order by s_id, start_time

编辑:由于对示例的新更改,按s_id添加了分区。

您可以在SQL Fiddle

中对此进行测试

答案 1 :(得分:0)

感谢您的回复。我已经在下面更新了查询。

peewee.UserDoesNotExist

上述查询对我有用,并给出了预期的结果。再次感谢您的所有回复。