【问题标题】:create sequence of numbers on grouped column in Oracle在Oracle中的分组列上创建数字序列
【发布时间】:2020-10-09 17:43:27
【问题描述】:

考虑下表的 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

【问题讨论】:

  • SQL 表代表 无序 集。您需要一个指定顺序的列。

标签: sql oracle gaps-and-islands


【解决方案1】:

您可以使用DENSE_RANK解析函数来获取A、B和C的每个组合的唯一ID。请注意,如果将新值插入表中,则A、B的每个组合的ID ,而 C 会发生变化,可能不一样。

查询

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

【讨论】:

  • 您是否使用 OP 的预期输出验证了您的输出?
  • 提供的示例输出 OP 没有逻辑顺序,因此除非 OP 另有说明,否则分配给 A、B 和 C 的每个组合的 RN 并不重要,只要它是唯一的每个组合。
  • @Sujitmohanty30,我更新了分析函数的顺序以匹配 OP 输出。以这种方式排序没有多大意义,但它可以完成工作。
【解决方案2】:

首先:为了让您的答案完全有意义,您需要一列来定义行的顺序。假设您有这样的专栏,名为id

然后,您可以使用窗口函数:

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

【讨论】:

    【解决方案3】:

    假设您有某种方式对行进行排序,那么您可以使用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;
    

    输出:

    一个 |乙| C |注册护士 -: | -: | -: | -: 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小提琴here

    【讨论】:

      【解决方案4】:

      也可以通过获取不同的组并对每个组进行编号来完成,而无需任何排序。借用 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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-28
        • 2018-08-09
        • 2015-01-12
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多