Oracle 推迟到下个月
如果我提出疑问:Oracle 推迟到下个月,oracle,oracle12c,Oracle,Oracle12c,如果我提出疑问: 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
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)
原因是,下个月到2是3,加上D。我猜按客户订单按月进行分区并不像我想的那样有效
在Oracle 12c中有没有实现这一点的方法?一种方法是使用范围分区和最小分析函数。像这样:
CUSTOMER MONTH PLAN np
1 1 A B
1 2 B D
1 2 C D
1 3 D (null)
当您使用范围分区时,您告诉Oracle根据您所排序的列的值来创建窗口,而不是根据行来创建窗口
因此,例如
+----------+-------+------+----+
| CUSTOMER | MONTH | PLAN | NP |
+----------+-------+------+----+
| 1 | 1 | A | B |
| 1 | 2 | B | D |
| 1 | 2 | C | D |
| 1 | 3 | D | |
+----------+-------+------+----+
。。。将创建一个包含下一行的窗口
ROWS BETWEEN 1 following and 1 following
。。。将创建一个窗口,其中包含具有下一个月值的所有行
使现代化
如果可能会跳过给定客户的某些月份值,则可以使用以下变量:
RANGE BETWEEN 1 following and 1 following
您可以使用滞后/超前两次。第一次检查重复月份并在这些月份中将值设置为NULL,第二次使用IGNORE NULLS获取下一个月值
它还有一个额外的好处,即如果跳过几个月,它仍然会找到下一个值
Oracle 11g R2架构设置:
问题1:
:
为了使它在此处作为Oracle 12c以后的选项列出,您可以使用应用运算符来解决这种类型的问题
| 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) |
我不知道有任何Oracle 12c公共小提琴,因此,SQL Server中的一个示例可以在这里找到:
评论我自己的答案。第一个_值不应该是确定的。我想我必须对行进行预排序,以保证在第一行中得到B而不是C。但我无法将其发送到第一行中的每个返回C,即使我对行进行预排序,以便C排在第一位。有什么评论吗?适用于Oracle-您也可以使用页面左上角的下拉列表更改数据库。@谢谢,但它不是Oracle 12c,也不是rextester或dbfiddle,apply运算符在11g中不可用。它是Oracle自己的服务,正在运行Oracle 18c。但你确实需要注册一个account@MTO再次感谢。是的,我知道这项服务,但我试图提供一个不在任何登录后面的fiddle地址。到目前为止,我还没有意识到任何事情,我相信总有一天会发生,但遗憾的是,现在还没有。
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 | |
+----------+-------+------+----+
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;
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
)
| 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) |
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
| customer | month | plan | np |
|----------|-------|------|--------|
| 1 | 1 | A | C |
| 1 | 2 | B | D |
| 1 | 2 | C | D |
| 1 | 3 | D | (null) |