Oracle 分析函数?

Oracle Analytical Function?

对于下面给定的table,我们如何找到名字连续出现3次的客户。

+---------+-----------+
| CUST_ID | CUST_NAME |
+---------+-----------+
| 1       | SAM       |
+---------+-----------+
| 2       | SAM       |
+---------+-----------+
| 3       | SAM       |
+---------+-----------+
| 4       | PETER     |
+---------+-----------+
| 5       | PETER     |
+---------+-----------+

Desired_Output

+-----------+
| CUST_NAME |
+-----------+
| SAM       |
+-----------+

Table定义:

create table Customer
(
  cust_id int,
  cust_name varchar2(20)
);

insert into customer values (1, 'SAM');
insert into customer values (2, 'SAM');
insert into customer values (3, 'SAM');
insert into customer values (4, 'PETER');
insert into customer values (5, 'PETER');

到目前为止尝试过的代码

Select distinct cust_name from (
select
cust_id,
cust_name,
lag(cust_name,1,0) over (order by cust_id)  as prev_cust_name,
lead(cust_name,1,0) over (order by cust_id) as next_cust_name
 from customer) a
 where a.prev_cust_name=a.next_cust_name;

我相信我们可以通过使用 lead/lag 获取上一行和下一行来做到这一点。虽然我的解决方案给出了所需的输出,但我认为这不是正确的解决方案。

你的方法很接近。您还需要一个比较:

select distinct cust_name 
from (select c.*
             lag(cust_name) over (order by cust_id)  as prev_cust_name,
             lead(cust_name) over (order by cust_id) as next_cust_name
      from customer c
     ) a c
where prev_cust_name = cust_name and cust_name = next_cust_name;

对于更通用的解决方案,您可以比较两个滞后:

select distinct cust_name 
from (select c.*
             lag(cust_id, 2) over (order by cust_id)  as prev2_cust_id,
             lag(cust_id, 2) over (partitioin by name order by cust_id)  as prev2_cust_id_name
      from customer c
     ) a c
where prev2_cust_id = prev2_cust_id_name;

这向后看两行 -- 一次仅由 cust_id 和一次仅用于名称。如果 cust_id 值相同,则所有行都具有相同的名称。您可以将 2 调整为任意值。

如果你想找到 N 个连续的值,你可以使用 window 函数。请参见 N = 4 的示例:

with params (n) as (select 4 from dual) -- Set N = 4
select distinct cust_name
from (
  select
    cust_id, cust_name, n,
    min(cust_name) over 
      (order by cust_id rows between n - 1 preceding and current row) as mi,
    max(cust_name) over
      (order by cust_id rows between n - 1 preceding and current row) as ma,
    count(*) over
      (order by cust_id rows between n - 1 preceding and current row) as cnt
  from customer
  cross join params
) x
where mi = ma and cnt = n

参见 SQL Fiddle 中的 运行 示例。