我正在尝试根据一组item_id创建group_id。 item_id是单个组的一部分的唯一指示是item_ids是顺序的。例如,根据下面的前两列,我想要的输出是第三列:
item item_id group_id
ABC 282 2
ABC 283 2
ABC 284 2
ABC 285 2
ABC 051 3
ABC 052 3
ABC 189 4
ABC 231 5
ABC 232 5
ABC 233 5
ABC 234 5
ABC 247 6
ABC 248 6
ABC 249 6
ABC 250 6
ABC 091 7
ABC 092 7
group_id本身不一定必须是顺序的,它只需要是唯一的。我尝试使用以下代码:
create sequence seq
start with 1
minvalue 1
increment by 1
cache 20;
select seq.nextval from dual; --to initialize the sequence
select
item,
item_id,
case when diff = 1 then seq.currval else seq.nextval end group_id
from
(
select
item,
item_id,
(id - lag(id, 1, 0) over (order by 1) diff
from
(
select
item,
item_id
from
table
)
);
但是得到以下输出:
item item_id group_id
ABC 282 2
ABC 283 3
ABC 284 4
ABC 285 5
ABC 051 6
ABC 052 7
ABC 189 8
ABC 231 9
ABC 232 10
ABC 233 11
ABC 234 12
ABC 247 13
ABC 248 14
ABC 249 15
ABC 250 16
ABC 091 17
ABC 092 18
在查找问题的原因时,我找到了用户ShannonSeverance的excellent explanation,详细说明了我的解决方案不起作用的原因。但是,它没有就如何向前推进提出任何建议。
有没有人有任何想法?
答案 0 :(得分:1)
您遇到了问题,因为SQL表本质上是无序的。以下“应该”在逻辑上有效,尽管它在实践中不会:
select ii.*, (item_id - rownum) as grp_id
from item_ids ii;
按顺序减去行号的item_id序列是常量。您可以将其用于组,至少对于给定项目。要处理多个项目,请将值连接在一起:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii;
要真正完成这项工作,您需要添加order by
- 这可以保证select
的结果排序。这可能有用,假设组之间存在“漏洞”:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii
order by item, item_id;
否则,您需要其他一些列来确定项目的正确排序。