TABLE: HIST
CUSTOMER MONTH PLAN
1 1 A
1 2 B
1 2 C
1 3 D
如果我查询:
select h.*, lead(plan) over (partition by customer order by month) np from HIST h
我得到:
CUSTOMER MONTH PLAN np
1 1 A B
1 2 B C
1 2 C D
1 3 D (null)
但是我想要
CUSTOMER MONTH PLAN np
1 1 A B
1 2 B D
1 2 C D
1 3 D (null)
下个月2
与3
的原因是D
。我猜partition by customer order by month
不能按照我的想法工作。
在Oracle 12c中是否可以实现这一目标?
答案 0 :(得分:3)
一种实现方法是将RANGE
分区与MIN
分析函数一起使用。像这样:
select h.*,
min(plan) over
(partition by customer
order by month
range between 1 following and 1 following) np
from HIST h;
+----------+-------+------+----+ | CUSTOMER | MONTH | PLAN | NP | +----------+-------+------+----+ | 1 | 1 | A | B | | 1 | 2 | B | D | | 1 | 2 | C | D | | 1 | 3 | D | | +----------+-------+------+----+
使用RANGE
分区时,是在告诉Oracle根据要排序的列的 values 来创建窗口,而不是根据行来创建窗口。 / p>
例如,
ROWS BETWEEN 1 following and 1 following
...将创建一个包含下一行的窗口。
RANGE BETWEEN 1 following and 1 following
...将创建一个窗口,其中包含具有month
下一个值的所有行。
如果对于给定的客户,可能会跳过MONTH
的某些值,则可以使用此变体:
select h.*,
first_value(plan) over
(partition by customer
order by month
range between 1 following and unbounded following) np
from h
+----------+-------+------+----+ | CUSTOMER | MONTH | PLAN | NP | +----------+-------+------+----+ | 1 | 1 | A | B | | 1 | 3 | B | D | | 1 | 3 | C | D | | 1 | 4 | D | | +----------+-------+------+----+
答案 1 :(得分:2)
您可以使用LAG
/ LEAD
两次。第一次检查重复的月份,并将这些月份的值设置为NULL
,第二次使用IGNORE NULLS
获取下一个每月的值。
它的另一个好处是,如果跳过了几个月,它仍然会找到下一个值。
Oracle 11g R2架构设置:
CREATE TABLE HIST ( CUSTOMER, MONTH, PLAN ) AS
SELECT 1, 1, 'A' FROM DUAL UNION ALL
SELECT 1, 2, 'B' FROM DUAL UNION ALL
SELECT 1, 2, 'C' FROM DUAL UNION ALL
SELECT 1, 3, 'D' FROM DUAL UNION ALL
SELECT 2, 1, 'E' FROM DUAL UNION ALL
SELECT 2, 1, 'F' FROM DUAL UNION ALL
SELECT 2, 3, 'G' FROM DUAL UNION ALL
SELECT 2, 5, 'H' FROM DUAL;
查询1 :
SELECT CUSTOMER,
MONTH,
PLAN,
LEAD( np ) IGNORE NULLS OVER ( PARTITION BY CUSTOMER ORDER BY MONTH, PLAN, ROWNUM ) AS np
FROM (
SELECT h.*,
CASE MONTH
WHEN LAG( MONTH ) OVER ( PARTITION BY CUSTOMER ORDER BY MONTH, PLAN, ROWNUM )
THEN NULL
ELSE PLAN
END AS np
FROM hist h
)
Results :
| CUSTOMER | MONTH | PLAN | NP |
|----------|-------|------|--------|
| 1 | 1 | A | B |
| 1 | 2 | B | D |
| 1 | 2 | C | D |
| 1 | 3 | D | (null) |
| 2 | 1 | E | G |
| 2 | 1 | F | G |
| 2 | 3 | G | H |
| 2 | 5 | H | (null) |
答案 2 :(得分:2)
仅在此处将它作为Oracle 12c(向前)的选项列出,您可以使用Apply运算符来解决此类问题
select
h.customer, h.month, h.plan, oa.np
from hist h
outer apply (
select
h2.plan as np
from hist h2
where h.customer = h.customer
and h2.month > h.month
order by month
fetch first 1 rows only
) oa
order by
h.customer, h.month, h.plan
我不知道任何Oracle 12c公共玩弄,因此,可以在这里找到SQL Server中的示例:http://sqlfiddle.com/#!18/cd95e/1
| customer | month | plan | np |
|----------|-------|------|--------|
| 1 | 1 | A | C |
| 1 | 2 | B | D |
| 1 | 2 | C | D |
| 1 | 3 | D | (null) |