为一组生成具有相同值的序列

Generating Sequence with Same Values for a Group

我低于 table 中的值:

|  Val1  |  
| 201900 |  
| 201910 |  
| 201920 |
| 201930 |
| 201901 |
| 201911 |
| 201921 |  
| 201931 |  
| 201902 |  
| 201912 | 
| 201922 | 
| 201932 |  

最后一位是2019年的级别(0,1,2,..)。倒数第二位是在特定日期有效的标识符。意味着 0 在 201900 中的 3 个月内有效,3 个月后将添加新值,即 201910。例如,对于级别 0 和 1,在给定时间将有两个不同的活动记录,即 201900 和 201901。我想为这两条记录分配相同的序列号。输出应如下所示:

|  Val1  | Seq |  
| 201900 |  1  |
| 201910 |  2  |
| 201920 |  3  |
| 201930 |  4  |
| 201901 |  1  | 
| 201911 |  2  |
| 201921 |  3  |
| 201931 |  4  |
| 201902 |  1  |
| 201912 |  2  |
| 201922 |  3  |
| 201932 |  4  |

我正在使用 Snowflake 云 DW,但 Oracle 语法应该可以正常工作。但是 Snowflake 没有序列中的 CurrVal 选项。
我正在尝试这个但不起作用:

> (SUBSTRING(Val1,6,1)=0 OR SUBSTRING(Val1,6,1)=1
> OR SUBSTRING(Val1,6,1)=2 OR
> SUBSTRING(Val1,6,1)=3 OR SUBSTRING(Val1,6,1)=4 
>     OR SUBSTRING(Val1,6,1)=5) THEN (SELECT  s.nextval FROM table(getnextval(test_seq)) s)

是这样的吗?有用的部分是第 16-17 行。

SQL> with test (val1) as
  2    (select 201900 from dual union all
  3     select 201910 from dual union all
  4     select 201920 from dual union all
  5     select 201930 from dual union all
  6     select 201901 from dual union all
  7     select 201911 from dual union all
  8     select 201921 from dual union all
  9     select 201931 from dual union all
 10     select 201902 from dual union all
 11     select 201912 from dual union all
 12     select 201922 from dual union all
 13     select 201932 from dual
 14    )
 15  select val1,
 16    row_number() over (partition by substr(val1, 1, 4), substr(val1, -1)
 17                       order by substr(val1, 5, 1)) seq
 18  from test;

      VAL1        SEQ
---------- ----------
    201900          1
    201910          2
    201920          3
    201930          4
    201901          1
    201911          2
    201921          3
    201931          4
    201902          1
    201912          2
    201922          3
    201932          4

12 rows selected.

SQL>

如果 VAL1 列的数据类型是 NUMBER 那么为什么不这样做呢?

with test (val1) as
  (select 201900 from dual union all
   select 201910 from dual union all
   select 201920 from dual union all
   select 201930 from dual union all
   select 201901 from dual union all
   select 201911 from dual union all
   select 201921 from dual union all
   select 201931 from dual union all
   select 201902 from dual union all
   select 201912 from dual union all
   select 201922 from dual union all
   select 201932 from dual)
select val1,
  row_number() over (partition by trunc(val1/100), mod(val1, 10)
                     order by mod(trunc(val1/10), 10)) seq
from test;

输出:

+--------+-----+
|  VAL1  | SEQ |
+--------+-----+
| 201900 |   1 |
| 201910 |   2 |
| 201920 |   3 |
| 201930 |   4 |
| 201901 |   1 |
| 201911 |   2 |
| 201921 |   3 |
| 201931 |   4 |
| 201902 |   1 |
| 201912 |   2 |
| 201922 |   3 |
| 201932 |   4 |
+--------+-----+

更新#1:

你问的是OUTER JOIN. But maybe you need the functionality of the LAG解析函数?我还认为没有必要按标识符排序,因为在按年份和级别分区后,VAL1 列值为我们提供了结果分区中的自然排序。

with
  test (val1) as
  (select 201900 from dual union all
   select 201910 from dual union all
   select 201920 from dual union all
   select 201930 from dual union all
   select 201901 from dual union all
   select 201911 from dual union all
   select 201921 from dual union all
   select 201931 from dual union all
   select 201902 from dual union all
   select 201912 from dual union all
   select 201922 from dual union all
   select 201932 from dual),
  t as
  (select
     test.*,
     row_number() over (partition by trunc(val1/100), mod(val1, 10)
                        order by val1) as seq
   from test)
select
  a.*, b.val1 as prev_value
from t a
left outer join t b
  on trunc(a.val1/100) = trunc(b.val1/100) and
     mod(a.val1, 10) = mod(b.val1, 10) and
     a.seq = b.seq + 1
order by trunc(a.val1/100), mod(a.val1, 10), a.val1;

输出:

+--------+-----+------------+
|  VAL1  | SEQ | PREV_VALUE |
+--------+-----+------------+
| 201900 |   1 |            |
| 201910 |   2 |     201900 |
| 201920 |   3 |     201910 |
| 201930 |   4 |     201920 |
| 201901 |   1 |            |
| 201911 |   2 |     201901 |
| 201921 |   3 |     201911 |
| 201931 |   4 |     201921 |
| 201902 |   1 |            |
| 201912 |   2 |     201902 |
| 201922 |   3 |     201912 |
| 201932 |   4 |     201922 |
+--------+-----+------------+

LAG解析函数:

with test (val1) as
  (select 201900 from dual union all
   select 201910 from dual union all
   select 201920 from dual union all
   select 201930 from dual union all
   select 201901 from dual union all
   select 201911 from dual union all
   select 201921 from dual union all
   select 201931 from dual union all
   select 201902 from dual union all
   select 201912 from dual union all
   select 201922 from dual union all
   select 201932 from dual)
select val1,
  lag(val1) over (partition by trunc(val1/100), mod(val1, 10)
                  order by val1) as prev_value
from test;

输出:

+--------+------------+
|  VAL1  | PREV_VALUE |
+--------+------------+
| 201900 |            |
| 201910 |     201900 |
| 201920 |     201910 |
| 201930 |     201920 |
| 201901 |            |
| 201911 |     201901 |
| 201921 |     201911 |
| 201931 |     201921 |
| 201902 |            |
| 201912 |     201902 |
| 201922 |     201912 |
| 201932 |     201922 |
+--------+------------+

使用 db<>fiddle 在线测试。