Oracle 基于日期列的字母顺序分配

Oracle Sequential assignment of alphabets based on date column

Table 1:

|Trans|Inc|Date|Status|
-----------------------
|1|1|01/01/2022|null
|5|1|20/01/2022|null
|3|1|03/01/2022|null
|11|2|01/01/2022|null
|3|2|13/12/2021|null

结果应该是

|Trans|Inc|Date|Status|
-----------------------
|1|1|01/01/2022|A
|5|1|20/01/2022|C
|3|1|03/01/2022|B
|11|2|01/01/2022|B
|3|2|13/12/2021|A

逻辑: Table1 有 4 列,状态列应按以下条款更新: 1 Inc 可以附加多个 trans。所以状态应该在日期列的基础上更新。前任。对于 Inc 1,我们有 4 个 trans(因此会有状态 A、B、C、D)和 Tran 1 日期为 01/01/2022,因此状态为 'A',第二条记录用于 inc 1 tran 3,日期是 03/01/2022,所以状态是 B。基本上我们需要根据日期列按字母顺序分配状态。

为此需要帮助。

您可以在此处使用 ROW_NUMBER

SELECT Trans, Inc, Date,
       SUBSTR('ABCDEFGHIJKLMNOPQRSTUVWXYZ',
              ROW_NUMBER() OVER (PARTITION BY Inc ORDER BY Date), 1) AS Status
FROM yourTable;

这里的技巧是根据每组公司记录中每条记录的行号位置取一个字母的 1 子串。

您可以使用:

SELECT Trans,
       Inc,
       "DATE",
       CASE
       WHEN rn < 26      THEN    CHR(65 + rn)
       WHEN rn < 27 * 26 THEN    CHR(65 + MOD(FLOOR((rn-26)/POWER(26,1)),26))
                              || CHR(65 + MOD(FLOOR((rn-26)/POWER(26,0)),26))
                         ELSE    CHR(65 + MOD(FLOOR((rn-27*26)/POWER(26,2)),26))
                              || CHR(65 + MOD(FLOOR((rn-27*26)/POWER(26,1)),26))
                              || CHR(65 + MOD(FLOOR((rn-27*26)/POWER(26,0)),26))
       END AS status
FROM   (
  SELECT Trans,
         Inc,
         "DATE",
         ROW_NUMBER() OVER (PARTITION BY Inc ORDER BY "DATE") - 1 AS rn
  FROM   table_name t
);

其中,对于示例数据:

CREATE TABLE table_name (Trans, Inc, "DATE", Status) AS
SELECT  1, 1, DATE '2022-01-01', CAST(NULL AS VARCHAR2(3)) FROM DUAL UNION ALL
SELECT  5, 1, DATE '2022-01-20', CAST(NULL AS VARCHAR2(3)) FROM DUAL UNION ALL
SELECT  3, 1, DATE '2022-01-03', CAST(NULL AS VARCHAR2(3)) FROM DUAL UNION ALL
SELECT 11, 2, DATE '2022-01-01', CAST(NULL AS VARCHAR2(3)) FROM DUAL UNION ALL
SELECT  3, 2, DATE '2021-12-13', CAST(NULL AS VARCHAR2(3)) FROM DUAL;

这将输出从 AZ 然后 AAZZ 然后 AAAZZZ 每个 INC值。

输出:

TRANS INC DATE STATUS
1 1 2022-01-01 00:00:00 A
3 1 2022-01-03 00:00:00 B
5 1 2022-01-20 00:00:00 C
3 2 2021-12-13 00:00:00 A
11 2 2022-01-01 00:00:00 B

如果您想更新状态值,那么您可以 MERGE 使用 ROWID 伪列进行关联:

MERGE INTO table_name dst
USING (
  SELECT ROWID AS rid,
         CASE
         WHEN rn < 26      THEN    CHR(65 + rn)
         WHEN rn < 27 * 26 THEN    CHR(65 + MOD(FLOOR((rn-26)/POWER(26,1)),26))
                                || CHR(65 + MOD(FLOOR((rn-26)/POWER(26,0)),26))
                           ELSE    CHR(65 + MOD(FLOOR((rn-27*26)/POWER(26,2)),26))
                                || CHR(65 + MOD(FLOOR((rn-27*26)/POWER(26,1)),26))
                                || CHR(65 + MOD(FLOOR((rn-27*26)/POWER(26,0)),26))
         END AS status
  FROM   (
    SELECT ROW_NUMBER() OVER (PARTITION BY Inc ORDER BY "DATE") - 1 AS rn
    FROM   table_name t
  )
) src
ON (src.rid = dst.ROWID)
WHEN MATCHED THEN
  UPDATE
  SET status = src.status;

db<>fiddle here