在 Oracle 中的分组列上创建数字序列

create sequence of numbers on grouped column in Oracle

考虑下面 table 的 a、b、c 列。

a   b   c
3   4   5
3   4   5
6   4   1
1   1   8
1   1   8
1   1   0
1   1   0

我需要一个 select 语句来得到下面的输出。即基于列 a、b、c 的组增加列 'rn'。

a   b   c   rn
3   4   5   1
3   4   5   1
6   4   1   2
1   1   8   3
1   1   8   3
1   1   0   4
1   1   0   4

作为初学者:为了使您的答案完全有意义,您需要一个列来定义行的顺序。让我假设您有这样的专栏,名为 id.

然后,您可以使用window函数:

select a, b, c, 
    sum(case when a = lag_a and b = lag_b and c = lag_c then 0 else 1 end) over(order by id) rn
from (
    select t.*,
        lag(a) over(order by id) lag_a,
        lag(b) over(order by id) lag_b,
        lag(c) over(order by id) lag_c
    from mytable t
) t

您可以使用 DENSE_RANK 解析函数为 A、B 和 C 的每个组合获取唯一 ID。请注意,如果在 table 中插入新值,则A、B、C各组合的ID会发生偏移,可能不一样。

查询

WITH
    my_table (a, b, c)
    AS
        (SELECT 3, 4, 5 FROM DUAL
         UNION ALL
         SELECT 3, 4, 5 FROM DUAL
         UNION ALL
         SELECT 6, 4, 1 FROM DUAL
         UNION ALL
         SELECT 1, 1, 8 FROM DUAL
         UNION ALL
         SELECT 1, 1, 8 FROM DUAL
         UNION ALL
         SELECT 1, 1, 0 FROM DUAL
         UNION ALL
         SELECT 1, 1, 0 FROM DUAL)
SELECT t.*, DENSE_RANK () OVER (ORDER BY b desc, c desc, a) as rn
  FROM my_table t;

结果

   A    B    C    RN
____ ____ ____ _____
   3    4    5     1
   3    4    5     1
   6    4    1     2
   1    1    8     3
   1    1    8     3
   1    1    0     4
   1    1    0     4

假设您有某种方式对行进行排序,那么您可以使用 MATCH_RECOGNIZE:

SELECT a, b, c, rn
FROM   table_name
MATCH_RECOGNIZE (
  ORDER BY id
  MEASURES MATCH_NUMBER() AS rn
  ALL ROWS PER MATCH
  PATTERN ( FIRST_ROW EQUAL_ROWS* )
  DEFINE EQUAL_ROWS AS (
      EQUAL_ROWS.a = PREV( EQUAL_ROWS.a )
  AND EQUAL_ROWS.b = PREV( EQUAL_ROWS.b )
  AND EQUAL_ROWS.c = PREV( EQUAL_ROWS.c )
  )
)

因此,对于您的测试数据:

CREATE TABLE table_name ( id, a, b, c ) AS
SELECT 1, 3, 4, 5 FROM DUAL UNION ALL
SELECT 2, 3, 4, 5 FROM DUAL UNION ALL
SELECT 3, 6, 4, 1 FROM DUAL UNION ALL
SELECT 4, 1, 1, 8 FROM DUAL UNION ALL
SELECT 5, 1, 1, 8 FROM DUAL UNION ALL
SELECT 6, 1, 1, 0 FROM DUAL UNION ALL
SELECT 7, 1, 1, 0 FROM DUAL;

输出:

 A |  B |  C | RN
-: | -: | -: | -:
 3 |  4 |  5 |  1
 3 |  4 |  5 |  1
 6 |  4 |  1 |  2
 1 |  1 |  8 |  3
 1 |  1 |  8 |  3
 1 |  1 |  0 |  4
 1 |  1 |  0 |  4

db<>fiddle here

也可以在没有任何顺序的情况下完成,方法是获取不同的组并对每个组进行编号。借用 EJ Egjed 的第一部分:

WITH  my_table (a, b, c)  AS
        (SELECT 3, 4, 5 FROM DUAL
         UNION ALL
         SELECT 3, 4, 5 FROM DUAL
         UNION ALL
         SELECT 6, 4, 1 FROM DUAL
         UNION ALL
         SELECT 1, 1, 8 FROM DUAL
         UNION ALL
         SELECT 1, 1, 8 FROM DUAL
         UNION ALL
         SELECT 1, 1, 0 FROM DUAL
         UNION ALL
         SELECT 1, 1, 0 FROM DUAL)
, groups as (select distinct a, b, c
            from my_table)
, groupnums as (select rownum as num, a, b, c 
           from groups)
select a, b, c, num
from   my_table join groupnums using(a,b,c);