如何跳过具有相同值的记录?

时间:2016-07-14 00:06:40

标签: sql oracle

我有一个表存储大量这样的记录:

Time  UserName  
10:30   John   
10:40   John  
10:45   John  
11:05   Sara  
11:07   John   
11:08   Ned  
11:09   Ned  

但是我需要以某种方式跳过与之前记录中相同UserName的记录,因此只有第一个UserName的记录才会出现,如下所示:

Time  UserName  
10:30   John   
11:05   Sara  
11:07   John   
11:08   Ned  

如何在常规编程语言中执行此操作非常明显,但我无法理解如何在SQL中执行此操作。

4 个答案:

答案 0 :(得分:3)

下面的查询使用“gap and islands”方法(a.k.a。“tabibitosan”方法)将具有相同username的CONSECUTIVE行组合在一起。

这仅适用于所有时间都不同的情况(否则row_number()的输出不确定);但如果时间并非完全不同,那么无论如何都没有“连续”名称的“自然”意义(在这种情况下,问题本身需要澄清)。

select min(time) as time, username from
    (select time, username,
            row_number() over (order by time) -
                   row_number() over (partition by username order by time) as gp
     from   inputs
    )
group by username, gp
order by time;

inputs是基表。

答案 1 :(得分:3)

我认为最简单的方法是使用lag()

select t.time, t.name
from (select t.*,
             lag(name) over (order by time) as prev_name
      from t
     ) t
where prev_name is null or prev_name <> name;

我认为这也是最好的表现。

答案 2 :(得分:1)

类似这样的事情

select t1.Time  ,t1.UserName from 
   ( select Time  ,UserName
    ,ROW_NUMBER() OVER (  ORDER BY Time,UserName ) R from table) t1
    join ( select Time  ,UserName
    ,ROW_NUMBER() OVER (  ORDER BY Time,UserName ) R from table) t2
    on t1.R = t2.R - 1
    where t1.UserName <> t2.UserName;

答案 3 :(得分:1)

这适用于所有没有分析功能的DB:

select * from temp t1 
where not exists ( select 1 from temp t2 
       where t2.UserName = t1.UserName
         and t2.Time < t1.Time 
         and not exists (select 1 from temp t3 
                where t3.UserName != t2.UserName 
                and t3.Time > t2.Time 
                and t3.Time < t1.Time 
                        ) 
                 ) ;

内部查询确保在其他名称之前没有出现其他相同的名称。