使用序列创建组ID

时间:2013-08-30 01:21:41

标签: sql oracle sequence

我正在尝试根据一组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,详细说明了我的解决方案不起作用的原因。但是,它没有就如何向前推进提出任何建议。

有没有人有任何想法?

1 个答案:

答案 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;

否则,您需要其他一些列来确定项目的正确排序。