简体   繁体   English

Oracle 12c-在窗口中选择记录

[英]Oracle 12c - select records within a window

I have the following sample records: 我有以下示例记录:

log_id employee_id
12345  99999      
12346  99999      
12347  88888      
12357  88888 

How do I filter records where log_id = 12345, 12346 (log_id only 1 number apart) when there duplicate employee_id's? 当存在重复的employee_id时,如何过滤log_id = 12345、12346(log_id仅相隔1个数字)的记录? Output should be: 输出应为:

log_id employee_id
12345  99999      
12346  99999 

I would not use window functions. 我不会使用窗口功能。 I would simply use exists : 我会简单地使用exists

select t.*
from t
where exists (select 1
              from t tnext
              where tnext.log_id = t.log_id + 1 and tnext.employee_id = t.employee_id) or
      exists (select 1
              from t tprev
              where tprev.log_id = t.log_id - 1 and tprev.employee_id = t.employee_id);

This query should be able to take advantage of an index on (employee_id, log_id) . 该查询应该能够利用(employee_id, log_id)上的索引。

I would try something like this: 我会尝试这样的事情:

with 
x as (
  select log_id, employee_id, row_number() over(order by log_id) as rn
  from my_table
),
y as (
  select
    log_id, employee_id, rn,
    lag(log_id) over(order by rn) as prev_log_id,
    lead(log_id) over(order by rn) as next_log_id
from x
)
select log_id, employee_id from y
where log_id - 1 = prev_log_id or prev_log_id is null
  and log_id + 1 = next_log_id or next_log_is is null
order by rn

Yet another option: 另一个选择:

SQL> with test (log_id, employee_id) as
  2    (select 12345, 99999 from dual union all
  3     select 12346, 99999 from dual union all
  4     select 12344, 99999 from dual union all  --> added this one
  5     --
  6     select 12347, 88888 from dual union all
  7     select 12357, 88888 from dual
  8    )
  9  select log_id, employee_id
 10  from test
 11  where employee_id in (select employee_id
 12                        from test
 13                        group by employee_id
 14                        having max(log_id) - min(log_id) = count(*) - 1
 15                       );

    LOG_ID EMPLOYEE_ID
---------- -----------
     12344       99999
     12346       99999
     12345       99999

SQL>

Assuming this table structure: 假设此表结构为:

create table test (
  log_id number(5) primary key,
  employee_id number(5) not null
)

This sample data: 此样本数据:

insert into test
   (select 12342, 99999 from dual union all
    select 12343, 77777 from dual union all
    select 12344, 99999 from dual union all
    select 12345, 99999 from dual union all
    select 12346, 99999 from dual union all
    select 12347, 88888 from dual union all
    -- gap
    select 12357, 88888 from dual union all
    select 12358, 33333 from dual union all
    select 12359, 33333 from dual
   )

You could do it with this query: 您可以使用以下查询来做到这一点:

with x as (
 select log_id,
        employee_id,
        lead(log_id) over (order by log_id) as next_log_id,
        lag(log_id) over (order by log_id) as previous_log_id,
        lead(employee_id) over (order by log_id) as next_employee_id,
        lag(employee_id) over (order by log_id) as previous_employee_id
 from test
)
select log_id, employee_id
  from x
 where (log_id = next_log_id - 1 and employee_id = next_employee_id)
    or (log_id = previous_log_id + 1 and employee_id = previous_employee_id)
 order by 1

With this result: 结果如下:

LOG_ID | EMPLOYEE_ID
-------+------------
 12344 |       99999
 12345 |       99999
 12346 |       99999
 12358 |       33333
 12359 |       33333

If you are guaranteed, to have the LOG_ID value sequence without gaps (as the sample has in range from 12342 to 12347), you could use a simpler variant: 如果可以保证, LOG_ID值序列没有间隙(因为样本的范围是12342到12347),则可以使用更简单的变体:

with x as (
 select log_id,
        employee_id,
        lead(employee_id) over (order by log_id) as next_employee_id,
        lag(employee_id) over (order by log_id) as previous_employee_id
 from test
 where log_id between 12342 and 12347
)
select log_id, employee_id
  from x
 where employee_id in (previous_employee_id, next_employee_id)
 order by 1

You can see it in action at this Oracle LiveSQL or this SQL Fiddle . 您可以在此Oracle LiveSQL或此SQL Fiddle中看到它的运行情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM