选择后果行并更改数据

时间:2014-07-22 07:06:55

标签: sql oracle oracle11g

示例数据

Name StartDate  Event
Ali 1/7/2010    garage
Ali 1/8/2010    garage
Ali 1/9/2010    garage
Ali 1/10/2010   aircond
Ali 1/11/2010   aircond
Ali 1/12/2010   aircond
Ali 1/13/2010   aircond
Ali 1/14/2010   garage
Ali 1/15/2010   yard
Ali 1/16/2010   dock
Ali 1/17/2010   dock

预期

Name    Start Date  Event
Ali 1/7/2010    garage
Ali 1/10/2010   aircond
Ali 1/14/2010   garage
Ali 1/15/2010   yard
Ali 1/16/2010   dock

尊敬的专家,

我有一个问题。我需要设计一个查询,这样只有在事件列中有更改时才能获取查询,就像我在预期的表中所做的那样。你能告诉我如何在sql oracle中执行此操作吗?

2 个答案:

答案 0 :(得分:2)

Alex Poole的LAG查询的简化版本:

select name, startdate, event
from
 (
    select name, startdate, event,
       case
          when event = 
             lag(event) over (partition by name order by startdate) 
          then 0 --same event
          else 1 --different event or no previous event 
       end as flag
    from t42
 )
where flag = 1
order by name, startdate, event;

fiddle

答案 1 :(得分:1)

这是一个“差距和岛屿”问题。

您可以使用子查询和lag分析函数来回顾之前的值 - 您可以在其中定义'{1}}和partition by子句中'previous'的含义 - 然后过滤基于:

order by

SQL Fiddle;或with the intermediate steps所以你可以看到发生了什么。最里面的查询添加了“滞后”列;下一层输出将当前值与滞后值进行比较,只有在它发生变化时才保留;并且外部查询排除那些在该过程之后为空的查询 - 也就是说,它排除那些更改的那些。

解决此类问题的另一种方法是将每个连续的值运行分配给存储桶,然后查找每个存储桶的第一个日期。您可以使用select name, startdate, event from ( select name, startdate, case when lag_event is null or lag_event != event then event end as event from ( select name, startdate, event, lag(event) over (partition by name order by startdate) as lag_event from t42 ) ) where event is not null order by name, startdate, event; NAME STARTDATE EVENT ---------- --------- ---------- Ali 07-JAN-10 garage Ali 10-JAN-10 aircond Ali 14-JAN-10 garage Ali 15-JAN-10 yard Ali 16-JAN-10 dock 分析函数为磁盘分配技巧:

row_number

然后将其用作子查询,使用聚合来获得您感兴趣的第一个日期:

select name, startdate, event,
  row_number() over (partition by name, event order by startdate)
    - row_number() over (partition by name order by startdate) as chain
from t42
order by name, startdate, event;

SQL Fiddle