如何确定Oracle SQL中的数字是否连续
这是我要问的前一个问题的第二部分。我有一个许可证号码表,并试图确定它们是否合法。我尝试运行的测试之一是数字是否是顺序/计数模式。真正有帮助的是,如果我能得到最大数量的连续字符,但我觉得这更难。例如:如何确定Oracle SQL中的数字是否连续,sql,regex,oracle,oracle11g,Sql,Regex,Oracle,Oracle11g,这是我要问的前一个问题的第二部分。我有一个许可证号码表,并试图确定它们是否合法。我尝试运行的测试之一是数字是否是顺序/计数模式。真正有帮助的是,如果我能得到最大数量的连续字符,但我觉得这更难。例如: LICENSE_NUMBER IS_COUNTING NUM_SEQ_CHARS 123456789 TRUE 9 123455678 FALSE 5 456789012 TRUE
LICENSE_NUMBER IS_COUNTING NUM_SEQ_CHARS
123456789 TRUE 9
123455678 FALSE 5
456789012 TRUE 9
12345 TRUE 5
123451234 FALSE 5
谢谢你的帮助
^(01(2345678901)*(2(3(4(5(6(7(8(90?)?)?)?)?)?)?)?)?
|12(3456789012)*(3(4(5(6(7(8(9(01?)?)?)?)?)?)?)?)?
|23(4567890123)*(4(5(6(7(8(9(0(12?)?)?)?)?)?)?)?)?
|34(5678901234)*(5(6(7(8(9(0(1(23?)?)?)?)?)?)?)?)?
|45(6789012345)*(6(7(8(9(0(1(2(34?)?)?)?)?)?)?)?)?
|56(7890123456)*(7(8(9(0(1(2(3(45?)?)?)?)?)?)?)?)?
|67(8901234567)*(8(9(0(1(2(3(4(56?)?)?)?)?)?)?)?)?
|78(9012345678)*(9(0(1(2(3(4(5(67?)?)?)?)?)?)?)?)?
|89(0123456789)*(0(1(2(3(4(5(6(78?)?)?)?)?)?)?)?)?
|90(1234567890)*(1(2(3(4(5(6(7(89?)?)?)?)?)?)?)?)?)$
它将匹配由两个或更多数字组成的任何字符串,该字符串完全由连续数字组成
123456789 MATCH
123455678 NOT MATCH
456789012 MATCH
12345 MATCH
演示:此查询还计算顺序字符的计数:
SELECT LICENSE_NUMBER,
CASE length( LICENSE_NUMBER ) WHEN max( cnt) THEN 'TRUE' ELSE 'FALSE' END As IS_COUNTING ,
max( cnt) As NUM_SEQ_CHARS
FROM (
SELECT LICENSE_NUMBER, p, count(*) As cnt
FROM (
SELECT LICENSE_NUMBER,
SUM( xx ) OVER ( Partition By LICENSE_NUMBER ORDER BY x ) As p
FROM (
SELECT LICENSE_NUMBER,
x, qq,
CASE WHEN qq - 1 = LAG( qq ) OVER ( Partition By LICENSE_NUMBER ORDER BY x )
THEN 0
WHEN qq = 0 AND 9 = LAG( qq ) OVER ( Partition By LICENSE_NUMBER ORDER BY x )
THEN 0
ELSE 1
END As xx
FROM (
SELECT LICENSE_NUMBER, x, substr( LICENSE_NUMBER, x, 1 ) qq
FROM (
SELECT *
FROM table
CROSS JOIN (
SELECT level x FROM dual
CONNECT BY LEVEL <= ( SELECT MAX( length( LICENSE_NUMBER )) FROM table )
)
)
)
)
)
GROUP BY LICENSE_NUMBER, p
)
GROUP BY LICENSE_NUMBER
以下是确定给定许可证号中连续递增位数的最大计数的有效方法。我不想麻烦处理YES/NO列——这可以通过比较MAX_计数和lengthlicense_数来获得。把它作为练习 我们需要将许可证编号分解为单个字符,并跟踪其位置。然后我们可以减去位置,取模10的余数。因为Oracle相信mod-1,10是-1,而不是9,他们真的需要回到小学重新学习模函数,所以我需要加上10,这样我在所有情况下都能得到正确的结果,解释下面解决方案中的一个奇怪之处。现在的问题是:为每个许可证编号找到最长的等距剩余序列mod 10 用所谓的Tabibitosan方法(即我在解决方案中称为prep的CTE中两个行号之差)可以最有效地找到序列中的连续内容。然后,一切都变成了分组、计数和取最大值的问题
您没有解释连续字符的计数,示例在这方面没有帮助。具体地说:您想知道字符串开头或字符串中的任意位置有多少位是按顺序排列的吗?3621234中的连续字符数是多少?是1还是4?回答得好。关于MOD函数:“当我使用一个单词时,”Humpty Dumpty用一种相当轻蔑的语气说,“它的意思就是我选择它的意思,既不多也不少。”“问题是,”爱丽丝说,“你是否能让单词有这么多不同的含义。”“问题是,”Humpty Dumpty说,“这就是主人,仅此而已。”。至少是Oracle。如果需要合适的模,它可以通过m-n*FLOORm/n来计算。@BobJarvis-如果Oracle选择使用exp来表示三角函数,因为我认为没有人会接受它。但问题是完全相同的。如果他们想拥有一个几乎与MOD相同的函数,除了它的行为不同之外负数,他们可以自由地这么做——但他们不能自由地称之为MOD。Don Knuth在创建Metafont时,就字体名称而言,非常清楚地指出了这一点。当然,很多傻瓜只是无视他所说的,造成了很多混乱——包括他们自己。@BobJarvis…哇,我刚刚看了一下文档ion,这真的很愚蠢请原谅我的法语。函数的名字是模,而不是模10是我的例子中的模;获得经典结果的方法不是像他们说的那样使用MOD,而是FLOOR;而且他们的例子表中仍然有不正确的经典模值。即使他们假装在解释我们之间的差异他们自己的版本和MOD的经典定义,他们仍然不理解经典定义。MOD总是非负的。他们似乎不明白。
with
-- begin of test data; not part of the solution
test_data ( license_number ) as (
select '123456789' from dual union all
select '123455678' from dual union all
select '456789012' from dual union all
select '12345' from dual union all
select '123451234' from dual union all
select '402023488' from dual union all
select '4189012' from dual
),
-- end of test data; solution (SQL query) continues below this line
tokenized ( license_number, idx, res ) as (
select license_number, level,
mod(10 + to_number(substr(license_number, level, 1)) - level, 10)
from test_data
connect by level <= length(license_number)
and prior license_number = license_number
and prior sys_guid() is not null
),
prep ( license_number, res, grp ) as (
select license_number, res,
row_number() over (partition by license_number order by idx) -
row_number() over (partition by license_number, res order by idx)
from tokenized
),
grouped ( license_number, res, grp, ct ) as (
select license_number, res, grp, count(*)
from prep
group by license_number, res, grp
)
select license_number, max(ct) as max_count
from grouped
group by license_number
;
LICENSE_NUMBER MAX_COUNT
-------------- ---------
123455678 5
123456789 9
456789012 9
123451234 5
4189012 5
12345 5
402023488 3