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;
这将输出从 A
到 Z
然后 AA
到 ZZ
然后 AAA
到 ZZZ
每个 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
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;
这将输出从 A
到 Z
然后 AA
到 ZZ
然后 AAA
到 ZZZ
每个 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