drop table foo;
create table foo (c1 varchar2(10), c2 int);
insert into foo values ('A', 10);
insert into foo values ('A', 11);
insert into foo values ('B', 12);
insert into foo values ('B', 13);
create sequence foo_s;
我希望按C1(A或B)对这些行进行分组,并为同一组中的每一行生成一个序号值。例如,C1=A的两行应具有相同的序号生成编号(例如1024),而C1=B的两行应具有相同的序号生成编号(例如1025):
我想做一些类似下面的事情,当然这是无效的语法:
select c1, c2, foo_s.nextval over (partition by c1) batch_id
from foo
其输出如下:
c1 | c2 | batch_id
A | 10 | 1024
A | 11 | 1024
B | 12 | 1025
B | 13 | 1025
我想在纯SQL的Select语句中执行此操作。如果失败,我想合并/更新是可以的。作为最后的手段,我可以在PL/SQL中执行此操作。
此solution使用了MERGE而不是SELECT,并且在ORA-02287中失败:此处不允许序列号
在PostgreSQL中,可以这样使用序列。例如:
select c1, c2, first_value(batch_id) over (partition by c1)
from (
select c1, c2, nextval('foo_s') batch_id from foo
) foo;
还有其他几种替代方法,但在Oracle中使用序列似乎总是会导致ORA-02287:此处不允许序列号。
4条答案
按热度按时间lpwwtiir1#
您评论说最终结果将位于另一个表中;你没有发布它,所以我会假设几件事-看看它是否有帮助。
这是一个源表(您已提交):
这是一个目标表:
查询不需要任何序列(作为Oracle对象);CTE查找最后一个
batch_id
,然后添加由dense_rank
分析函数生成的值:目标表的内容:
现在,由于您没有解释如何生成下一个数据集,我将截断源表并向其中插入更多的行,您可能会有一些日期列(因此您将始终使用"今天的数据"),或者......除了您之外,谁知道呢?
重新运行相同的
INSERT
语句:这导致了
batch_id
会按照您的要求递增。mqkwyuun2#
hi3rlvi23#
重复分配每个查询:
仅当存在新的C1值时才分配新的批次1值:
8ulbf1ek4#
你可以将
sequence.nextval
分离成一个函数,并在任何地方使用这个函数。从12c开始,在select
语句中声明函数是可能的。| C1|C2|批次ID|
| - ------|- ------|- ------|
| 乙|十二|第二章|
| 乙|十三|第二章|
| A类|十个|1个|
| A类|十一|1个|
| C1|C2|批次ID|
| - ------|- ------|- ------|
| A类|十个|三个|
| A类|十一|三个|
| 乙|十二|四个|
| 乙|十三|四个|
fiddle
或者,如果您希望避免对
foo
的双重访问,请对match_recognize
执行相同的操作:fiddle
...或使用
model
:fiddle