在多个(相同)位置花费的时间-可能是窗口功能吗?

时间:2019-03-05 14:25:11

标签: sql-server oracle

每种颜色都是一个位置。这是根据“开始”日期排序的,需要保持这种方式才能找到第一个位置,第二个位置等。由于各种原因,该位置可能会显示多次。我需要每个“窗口”或ID LOC的最早开始日期和最后结束日期。希望下面的例子清晰易懂。我在SQL Server中工作。可以在Oracle中完成。我尝试了各种窗口功能... first_value,last_value,lead,lag,采用不同组合的不同方式进行分区,并且没有运气。实际数据将具有许多不同的ID,因此应成为分区的一部分。 谢谢您的帮助。

这是示例数据:

+----------------------------------------------------+
|ID   |LOC   |START              |END                |
+----------------------------------------------------+
|45334|RED   |2015-08-26 17:26:21|2015-08-26 20:17:00|
|45334|GREEN |2015-08-26 20:17:50|2015-08-30 21:01:00|
|45334|GREEN |2015-08-30 21:01:49|2015-09-02 15:19:00|
|45334|YELLOW|2015-09-02 15:19:33|2015-09-02 21:46:00|
|45334|GREEN |2015-09-02 21:46:36|2015-09-05 19:48:00|
|45334|BLUE  |2015-09-05 19:48:26|2015-09-05 20:33:00|
|45334|YELLOW|2015-09-05 20:33:11|2015-09-05 21:27:00|
|45334|BLACK |2015-09-05 21:27:38|2015-09-07 16:48:09|
|45334|BLACK |2015-09-07 16:48:09|2015-09-08 18:30:00|
|45334|GREEN |2015-09-08 18:35:13|2015-09-10 11:15:23|
|45334|GREEN |2015-09-10 11:15:23|2015-09-10 20:32:00|
|45334|GREEN |2015-09-10 20:32:57|2015-09-16 15:22:58|
|45334|GREEN |2015-09-16 15:22:58|2015-09-17 14:02:00|
|45334|YELLOW|2015-09-17 14:02:28|2015-09-17 17:04:00|
|45334|BLACK |2015-09-17 17:04:25|2015-09-18 11:36:03|
|45334|BLACK |2015-09-18 11:36:03|2015-09-18 21:48:00|
|45334|GREEN |2015-09-18 21:49:05|2015-09-21 11:22:29|
|45334|GREEN |2015-09-21 11:22:29|2015-09-21 18:54:00|
|45334|GREEN |2015-09-21 18:54:50|2015-09-23 13:39:00|
|45334|GREEN |2015-09-23 13:39:25|2015-09-23 16:12:00|
|45334|GREEN |2015-09-23 16:12:00|2015-09-23 16:25:00|
|45334|GREEN |2015-09-23 16:25:37|2015-10-02 15:13:00|
|45334|GREEN |2015-10-02 15:13:00|2015-10-02 15:13:00|
|45334|GREEN |2015-10-02 15:13:00|2015-10-02 15:13:00|
|45334|GREEN |2015-10-02 15:13:00|2015-10-02 15:13:00|
|45334|GREEN |2015-10-02 15:13:00|2015-10-02 15:13:00|
|45334|GREEN |2015-10-02 15:13:00|2015-10-02 15:13:00|
|45334|GREEN |2015-10-02 15:13:00|2015-10-02 15:13:00|
+----------------------------------------------------+

它应该是这样的:

+----------------------------------------------------+
|ID   |LOC   |START              |END                |
+----------------------------------------------------+
|45334|RED   |2015-08-26 17:26:21|2015-08-26 20:17:00|
|45334|GREEN |2015-08-26 20:17:50|2015-09-02 15:19:00|
|45334|YELLOW|2015-09-02 15:19:33|2015-09-02 21:46:00|
|45334|GREEN |2015-09-02 21:46:36|2015-09-05 19:48:00|
|45334|BLUE  |2015-09-05 19:48:26|2015-09-05 20:33:00|
|45334|YELLOW|2015-09-05 20:33:11|2015-09-05 21:27:00|
|45334|BLACK |2015-09-05 21:27:38|2015-09-08 18:30:00|
|45334|GREEN |2015-09-08 18:35:13|2015-09-17 14:02:00|
|45334|YELLOW|2015-09-17 14:02:28|2015-09-17 17:04:00|
|45334|BLACK |2015-09-17 17:04:25|2015-09-18 21:48:00|
|45334|GREEN |2015-09-18 21:49:05|2015-10-02 15:13:00|
+----------------------------------------------------+

2 个答案:

答案 0 :(得分:0)

当位置更改时,将标志分配为1。使用sum(flag) over (...)创建分组列。最后分组数据:

select id, min(loc), min(start_), max(end_)
  from (
    select a.*, sum(flag) over(order by start_) grp
      from (select t.*, case when loc <> lag(loc) over (order by start_) 
                             then 1 else 0 end flag from t) a )
  group by id, grp

dbfiddle demo

在Oracle中测试。在最终代码中添加partition by id

答案 1 :(得分:0)

您也可以使用Tabibitosan

select id,
       loc,
       to_char(min(start_), 'yyyy-mm-dd hh24:mi:ss') grp_start_time,
       to_char(max(end_), 'yyyy-mm-dd hh24:mi:ss') grp_end_time
from   (select t.*,
               row_number() over (partition by id order by start_, ROWNUM)
                 - row_number() over (partition by id, loc order by start_, ROWNUM) grp
        from t)
group by id, loc, grp

dbfiddle

我必须将rownum分析函数的顺序添加row_number(),因为示例数据中的行的开始和结束时间相同。如果每个id和loc的行的开始时间都不同,则不需要rownum

如果我是你,我将尝试两种解决方案,看看哪种对您的数据更有效,等等。(我很想了解您的结果;我怀疑其中没有什么,或者是Ponder的答案有优势。)