在最后

时间:2017-07-17 11:53:51

标签: sql oracle

我有这样的表格行。

acc start_dat   end_dat n_type
aa  1/1/2017    2/2/2017    er
aa  2/2/2017    4/2/2017    er
aa  4/2/2017    1/3/2017    ok
aa  1/3/2017    12/3/2017   ok
aa  12/3/2017   15/4/2017   er
aa  15/4/2017   3/5/2017    er
aa  3/5/2017    5/5/2017    er
aa  5/5/2017      null      ok
bb  12/2/2017   4/3/2017    er
bb  4/3/2017    20/3/2017   er
bb  20/3/2017   13/4/2017   er
bb  13/4/2017   4/5/2017    ok
bb  4/5/2017    7/6/2017    er
bb  7/6/2017    3/7/2017    er
bb  3/7/2017     null       ok

我想将更改前的最后一个状态分组为ok,end_Dat = null表示开始结束的计算日期

acc start_dat   end_dat duration_day
aa  12/3/2017   5/5/2017    52
bb  4/5/2017    3/7/2017    60

你有什么想法解决它吗?

2 个答案:

答案 0 :(得分:0)

您可以在每条记录之后计算“ok”记录的数量,然后将其用于聚合:

select acc, min(start_dat), max(end_dat),
       (max(end_dat) - min(start_dat)) as diff
from (select t.*,
             sum(case when n_type = 'ok' then 1 else 0 end) over (partition by acc order by start_dat desc) as numoks_after
      from t
     ) t
where numoks_after = 1 and n_type <> 'ok'
group by acc;

答案 1 :(得分:0)

你的数学似乎不正确,从2017年12月3日到2017年5月5日的日数是54,而不是52.这是一个错字吗?

您需要使用相同的n_type对连续的行进行分组。 &#34;连续&#34;按start_dat排序,并为每个acc分别完成分组。这是Tabibitosan方法的直接应用,用于在这样的&#34;间隙和岛屿中创建群组标识符。问题。 &#34; Tabibitosan方法&#34;是在下面的解决方案的最里面的子查询中使用两个row_number()函数的差异,使用不同的partition by子句。

除此之外,查询是标准的。按acc, n_type, grp分组(其中grp是在最里面的子查询中创建的新分组标志),计算每个组的最小开始日期和最大结束日期,并选择具有最高{{1}的组忽略grp

之后的所有组的标志
n_type = 'ok'