请假设您有一个由6个字符组成的VARCHAR2字符串:
LETTER LETTER DIGIT LETTER LETTER LETTER LETTER LETTER
其中LETTER = A,B,C,.....,W,X,Y,Z 和 NUMBER = 0,1,2,3,.....,9
以前规则的最小字符串是:AA0AAA 具有先前规则的最大字符串是:ZZ9ZZZ
可能的组合数量为:
26 * 26 * 10 * 26 * 26 * 26 = 118813760
如何解码AA0AAA为1,AA0AAB为2,AA0AAC为3,.....,ZZ9ZZZ为118813760?
我在Oracle PL / SQL中编程。
提前感谢您的合作。
这是我的代码但未优化:(
SELECT RIGA
FROM (SELECT ROWNUM riga, alfa.*
FROM (WITH s1 AS (SELECT 'A' list1 FROM DUAL
UNION ALL
SELECT 'B' FROM DUAL
UNION ALL
SELECT 'C' FROM DUAL
UNION ALL
SELECT 'D' FROM DUAL
UNION ALL
SELECT 'E' FROM DUAL
UNION ALL
SELECT 'F' FROM DUAL
UNION ALL
SELECT 'G' FROM DUAL
UNION ALL
SELECT 'H' FROM DUAL
UNION ALL
SELECT 'I' FROM DUAL
UNION ALL
SELECT 'J' FROM DUAL
UNION ALL
SELECT 'K' FROM DUAL
UNION ALL
SELECT 'L' FROM DUAL
UNION ALL
SELECT 'M' FROM DUAL
UNION ALL
SELECT 'N' FROM DUAL
UNION ALL
SELECT 'O' FROM DUAL
UNION ALL
SELECT 'P' FROM DUAL
UNION ALL
SELECT 'Q' FROM DUAL
UNION ALL
SELECT 'R' FROM DUAL
UNION ALL
SELECT 'S' FROM DUAL
UNION ALL
SELECT 'T' FROM DUAL
UNION ALL
SELECT 'U' FROM DUAL
UNION ALL
SELECT 'V' FROM DUAL
UNION ALL
SELECT 'W' FROM DUAL
UNION ALL
SELECT 'X' FROM DUAL
UNION ALL
SELECT 'Y' FROM DUAL
UNION ALL
SELECT 'Z' FROM DUAL),
s2 AS (SELECT 'A' list2 FROM DUAL
UNION ALL
SELECT 'B' FROM DUAL
UNION ALL
SELECT 'C' FROM DUAL
UNION ALL
SELECT 'D' FROM DUAL
UNION ALL
SELECT 'E' FROM DUAL
UNION ALL
SELECT 'F' FROM DUAL
UNION ALL
SELECT 'G' FROM DUAL
UNION ALL
SELECT 'H' FROM DUAL
UNION ALL
SELECT 'I' FROM DUAL
UNION ALL
SELECT 'J' FROM DUAL
UNION ALL
SELECT 'K' FROM DUAL
UNION ALL
SELECT 'L' FROM DUAL
UNION ALL
SELECT 'M' FROM DUAL
UNION ALL
SELECT 'N' FROM DUAL
UNION ALL
SELECT 'O' FROM DUAL
UNION ALL
SELECT 'P' FROM DUAL
UNION ALL
SELECT 'Q' FROM DUAL
UNION ALL
SELECT 'R' FROM DUAL
UNION ALL
SELECT 'S' FROM DUAL
UNION ALL
SELECT 'T' FROM DUAL
UNION ALL
SELECT 'U' FROM DUAL
UNION ALL
SELECT 'V' FROM DUAL
UNION ALL
SELECT 'W' FROM DUAL
UNION ALL
SELECT 'X' FROM DUAL
UNION ALL
SELECT 'Y' FROM DUAL
UNION ALL
SELECT 'Z' FROM DUAL),
k1 AS (SELECT '0' list3 FROM DUAL
UNION ALL
SELECT '1' FROM DUAL
UNION ALL
SELECT '2' FROM DUAL
UNION ALL
SELECT '3' FROM DUAL
UNION ALL
SELECT '4' FROM DUAL
UNION ALL
SELECT '5' FROM DUAL
UNION ALL
SELECT '6' FROM DUAL
UNION ALL
SELECT '7' FROM DUAL
UNION ALL
SELECT '8' FROM DUAL
UNION ALL
SELECT '9' FROM DUAL),
s3 AS (SELECT 'A' list4 FROM DUAL
UNION ALL
SELECT 'B' FROM DUAL
UNION ALL
SELECT 'C' FROM DUAL
UNION ALL
SELECT 'D' FROM DUAL
UNION ALL
SELECT 'E' FROM DUAL
UNION ALL
SELECT 'F' FROM DUAL
UNION ALL
SELECT 'G' FROM DUAL
UNION ALL
SELECT 'H' FROM DUAL
UNION ALL
SELECT 'I' FROM DUAL
UNION ALL
SELECT 'J' FROM DUAL
UNION ALL
SELECT 'K' FROM DUAL
UNION ALL
SELECT 'L' FROM DUAL
UNION ALL
SELECT 'M' FROM DUAL
UNION ALL
SELECT 'N' FROM DUAL
UNION ALL
SELECT 'O' FROM DUAL
UNION ALL
SELECT 'P' FROM DUAL
UNION ALL
SELECT 'Q' FROM DUAL
UNION ALL
SELECT 'R' FROM DUAL
UNION ALL
SELECT 'S' FROM DUAL
UNION ALL
SELECT 'T' FROM DUAL
UNION ALL
SELECT 'U' FROM DUAL
UNION ALL
SELECT 'V' FROM DUAL
UNION ALL
SELECT 'W' FROM DUAL
UNION ALL
SELECT 'X' FROM DUAL
UNION ALL
SELECT 'Y' FROM DUAL
UNION ALL
SELECT 'Z' FROM DUAL),
s4 AS (SELECT 'A' list5 FROM DUAL
UNION ALL
SELECT 'B' FROM DUAL
UNION ALL
SELECT 'C' FROM DUAL
UNION ALL
SELECT 'D' FROM DUAL
UNION ALL
SELECT 'E' FROM DUAL
UNION ALL
SELECT 'F' FROM DUAL
UNION ALL
SELECT 'G' FROM DUAL
UNION ALL
SELECT 'H' FROM DUAL
UNION ALL
SELECT 'I' FROM DUAL
UNION ALL
SELECT 'J' FROM DUAL
UNION ALL
SELECT 'K' FROM DUAL
UNION ALL
SELECT 'L' FROM DUAL
UNION ALL
SELECT 'M' FROM DUAL
UNION ALL
SELECT 'N' FROM DUAL
UNION ALL
SELECT 'O' FROM DUAL
UNION ALL
SELECT 'P' FROM DUAL
UNION ALL
SELECT 'Q' FROM DUAL
UNION ALL
SELECT 'R' FROM DUAL
UNION ALL
SELECT 'S' FROM DUAL
UNION ALL
SELECT 'T' FROM DUAL
UNION ALL
SELECT 'U' FROM DUAL
UNION ALL
SELECT 'V' FROM DUAL
UNION ALL
SELECT 'W' FROM DUAL
UNION ALL
SELECT 'X' FROM DUAL
UNION ALL
SELECT 'Y' FROM DUAL
UNION ALL
SELECT 'Z' FROM DUAL),
s5 AS (SELECT 'A' list6 FROM DUAL
UNION ALL
SELECT 'B' FROM DUAL
UNION ALL
SELECT 'C' FROM DUAL
UNION ALL
SELECT 'D' FROM DUAL
UNION ALL
SELECT 'E' FROM DUAL
UNION ALL
SELECT 'F' FROM DUAL
UNION ALL
SELECT 'G' FROM DUAL
UNION ALL
SELECT 'H' FROM DUAL
UNION ALL
SELECT 'I' FROM DUAL
UNION ALL
SELECT 'J' FROM DUAL
UNION ALL
SELECT 'K' FROM DUAL
UNION ALL
SELECT 'L' FROM DUAL
UNION ALL
SELECT 'M' FROM DUAL
UNION ALL
SELECT 'N' FROM DUAL
UNION ALL
SELECT 'O' FROM DUAL
UNION ALL
SELECT 'P' FROM DUAL
UNION ALL
SELECT 'Q' FROM DUAL
UNION ALL
SELECT 'R' FROM DUAL
UNION ALL
SELECT 'S' FROM DUAL
UNION ALL
SELECT 'T' FROM DUAL
UNION ALL
SELECT 'U' FROM DUAL
UNION ALL
SELECT 'V' FROM DUAL
UNION ALL
SELECT 'W' FROM DUAL
UNION ALL
SELECT 'X' FROM DUAL
UNION ALL
SELECT 'Y' FROM DUAL
UNION ALL
SELECT 'Z' FROM DUAL)
SELECT *
FROM S1,
S2,
K1,
S3,
S4,
S5) alfa)
WHERE LIST1 = 'A'
AND LIST2 = 'A'
AND LIST3 = '1'
AND LIST4 = 'A'
AND LIST5 = 'A'
AND LIST6 = 'A';
答案 0 :(得分:2)
在SQL Developer
上测试,输入位于变量in_string
:
declare
in_string varchar2(20):= 'ZZ9ZZZ';
type m IS VARRAY(6) OF INTEGER;
weights m;
in_char char(1);
cnt number := 0;
res number := 1;
BEGIN
weights:= m(4569760, 175760, 17576, 676, 26, 1);
while (cnt < length(in_string))
loop
cnt := cnt + 1;
in_char := substr(in_string, cnt, 1);
if cnt != 3 then
res := res + (ASCII(in_char) - 65) * weights(cnt);
else
res := res + (ASCII(in_char) - 48) * weights(cnt);
end if;
end loop;
DBMS_OUTPUT.PUT_LINE(res);
END;
/
给了我:118813760。
答案 1 :(得分:1)
您可以使用ascii函数将字母转换为数字。 &#39; A&#39; ascii = 65,&#39; Z&#39; = 90。 所以从结果中减去64并得到正确的值。
然后对于数字,加1(0映射到1,9映射到10)
请参阅下面的编辑,此部分不正确
将所有部分相乘,并且瞧:这是一个仅限SQL的解决方案。 比声明PL / SQL函数要快得多,因为对于每个结果,DB必须在SQL和PL / SQL上下文之间切换。
select t.string input
, to_number(ascii(substr(t.string,1,1))-64)
* to_number(ascii(substr(t.string,2,1))-64)
* (to_number(substr(t.string,3,1)) + 1)
* to_number(ascii(substr(t.string,4,1))-64)
* to_number(ascii(substr(t.string,5,1))-64)
* to_number(ascii(substr(t.string,6,1))-64) as value
from (select 'AA0AAA' string from dual
union all
select 'ZZ9ZZZ' string from dual
) t;
select ascii('Z') from dual;
编辑 - 改进答案 我看到了ProblemFactory的答案。他正在做对:有一个权重因素。 即AA0ZZZ应低于ZZ0ZAA,而上述版本返回相同。 但是,在他的解决方案中,需要一个声明的PL / SQL函数,这会在执行大型数据集时导致性能损失。
以下查询将返回正确的值(感谢ProblemFactory):
select t.string input
, to_number(ascii(substr(t.string,1,1))-65) * 4569760 --26*26*26*10*26
+ to_number(ascii(substr(t.string,2,1))-65) * 175760 --26*26*26*10
+ to_number(substr(t.string,3,1)) * 17576 --26*26*26
+ to_number(ascii(substr(t.string,4,1))-65) * 676 --26*26
+ to_number(ascii(substr(t.string,5,1))-65) * 26
+ to_number(ascii(substr(t.string,6,1))-64) as value
from (select 'AA0AAA' string from dual
union all
select 'ZZ9ZZZ' string from dual
) t;
结果
INPUT VALUE
------ ----------
AA0AAA 1
ZZ9ZZZ 118813760
答案 2 :(得分:0)
假设您的字符串格式是固定的,您可以通过编写一个更简单的pl / sql函数来解决这个问题,该函数接收单个字母并返回该字母的编号 - 例如,A = 0,Z = 25。 / p>
如果您知道该字母在字符串中的位置,您可以计算出该字母的价值,然后将其乘以适合该位置的26的幂。
答案 3 :(得分:0)
如果这是PL / SQL中的一个难题,那么aima中就有一个MixedRadixNumber java类。
当然可以从PL / SQL中调用java,如O'Reilly book中所述。