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 中的 运行 示例。
对于下面给定的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 中的 运行 示例。