增加重复行的计数器(不是通过PL / SQL)

时间:2016-10-18 00:56:29

标签: sql oracle duplicates

select IDX, SUB_IDX, NAME from MYTABLE order by IDX, SUB_IDX结果:

IDX SUB_IDX NAME
1   20  aaa
2   22  bbb
3   22  ccc
4   23  ddd
5   23  eee
6   23  fff

IDX是PK,我希望计算连续SUB_IDX的重复次数:

IDX SUB_IDX count   NAME
1   20      1       aaa
2   22      1       bbb
3   22      2       ccc
4   23      1       ddd
5   23      2       eee
6   23      3       fff

我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:2)

我想你想要count窗口函数:

select
  idx, sub_idx,
  count (1) over (partition by sub_idx order by idx) as count,
  name
from MYTABLE 

答案 1 :(得分:2)

  

我想计算重复 连续 SUB_IDX

由于您的 连续 要求,查询变得更加复杂。您的示例数据有点过于简单,并且没有清楚地显示出现非连续重复SUB_IDX值时您的预期输出。

尽管如此,假设我正确理解,结合一些分析函数,它是可能的。也许有人可以找到简化查询的方法:

with grp_starts as (
  select idx, sub_idx, name,
         case when sub_idx = lag(sub_idx) over (order by idx)
           then 0 else 1 end as is_grp_start
  from mytable),
grps as (
  select idx, sub_idx, name,
         sum(is_grp_start) over (order by idx) as grp_id
    from grp_starts)
select idx, 
       sub_idx,
       row_number() over (partition by grp_id order by idx) as count,
       name
  from grps

答案 2 :(得分:2)

假设你的意思并不是“连续”(通过什么排序标准“连续”?)而是你只想将连续数字分配给具有相同SUB_INDEX的行......并假设你想要分配这些数字增加(按字母顺序)NAME的顺序:

select idx, sub_idx, row_number() over (partition by sub_idx order by name) as ct, name
from table_name

count是Oracle中的保留字;不要将它用作列名。 (与DATE,LAST等相同)

答案 3 :(得分:1)

为了完整起见,这是另一种解决方案,与sstan非常相似,但是使用了#tab; tabibitosan"或者"平等差异"创建组的方法(而不是"组的开始"方法,这是更一般的,但在这种情况下效率较低,因为它读取相同的行两次而不是一次)。

可以应用tabibitosan方法的一般问题类别被称为" gap and islands"问题,或在一个或多个列中找到具有相同值的连续行序列(根据一些明确指定的顺序)。

注意row_number()子查询中对grps的两次调用的不同 - 这取代了"组"用"组开始"创建标志后跟一个运行总和。另外,请注意一旦"组"通过形成行数的差异,在最后(外部)查询中使用的组由此差异sub_idx,而不仅仅由row_number()差异(这是对方法的常见误解)。

我提供了OTN"社区文档的链接"在对sstan的解决方案的评论中关于tabibitosan方法。

在某些情况下,当idx是序列号(连续)时,可以使用row_number() over (order by idx)本身而不是idx。这是糟糕的编程,因为它依赖于特定的"物理"对数据的了解。我在下面写的解决方案不依赖于这些知识(为了演示,我添加了更多行,其中idx不是连续数字)。

with 
     t ( idx, sub_idx, name ) as (
       select  1, 20, 'aaa' from dual union all
       select  2, 22, 'bbb' from dual union all
       select  3, 22, 'ccc' from dual union all
       select  4, 23, 'ddd' from dual union all
       select  5, 23, 'eee' from dual union all
       select  6, 23, 'fff' from dual union all
       select  7, 22, 'ggg' from dual union all
       select  9, 22, 'hhh' from dual union all
       select 12, 20, 'iii' from dual union all
       select 18, 20, 'jjj' from dual
     ),
     grps ( idx, sub_idx, name, grp ) as (
       select idx, sub_idx, name,
              row_number() over (order by idx) - 
                  row_number() over (partition by sub_idx order by idx)
       from   t
     )
select idx, sub_idx, 
       row_number() over (partition by sub_idx, grp order by idx) as ct,
       name
from grps
order by idx   --  ORDER BY is optional
;

<强>输出

       IDX    SUB_IDX         CT  NAME
---------- ---------- ----------  ----
         1         20          1  aaa
         2         22          1  bbb
         3         22          2  ccc
         4         23          1  ddd
         5         23          2  eee
         6         23          3  fff
         7         22          1  ggg
         9         22          2  hhh
        12         20          1  iii
        18         20          2  jjj

 10 rows selected