让char为s
,字符串为mississsipisssss
。 sql应返回5.
我正在考虑使用
来化妆 regexp_count(string,'s+')
将返回连续序列s
的子串数。
REGEXP_INSTR(string,'s',1,m)
将返回char s
的第m个位置(第m个序列的起始位置)
REGEXP_INSTR(string,'s[^s]',1,m)
将返回char s
的第m个位置(第m个序列的结束位置)
我还没有找到任何解决方案。但我不认为这是一种正确的方法,因为字符串可以是任何长度,并且可以有任意数量的这种连续序列。有人可以提出任何解决方案的想法(我是初学者)
答案 0 :(得分:1)
这将在sql-server 2008 +中运行。相同的概念在Oracle中可以使用,您只需要添加一些语法差异,例如SUBSTR而不是SUBSTRING。以下是转换为Oracle语法的快速尝试:
CREATE GLOBAL TEMPORARY TABLE TempTable
(String VARCHAR(100)) ON COMMIT PRESERVE ROWS;
INSERT INTO TempTable (String) VALUES ('mississsipisssss');
INSERT INTO #TempTable (String) VALUES ('ssasdfs');
WITH cteTokens (String, IndexNum, Token, CharCount) AS (
SELECT
String
,1 as IndexNum
,SUBSTR(t.String,1,1) as Token
,CASE WHEN SUBSTR(t.String,1,1) = 's' THEN 1 ELSE 0 END As CharCount
FROM
#TempTable t
UNION ALL
SELECT
t.String
IndexNum + 1 as IndexNum
,SUBSTR(t.String,IndexNum + 1,1) as Token
,CASE WHEN SUBSTR(t.String,IndexNum + 1,1) = 's' THEN t.CharCount + 1 ELSE 0 END AS CharCount
FROM
#TempTable s
INNER JOIN cteTokens t
ON s.String = t.String
AND LENGTH(s.String) >= t.IndexNum + 1
)
SELECT
String
,MAX(CharCount)
FROM
cteTokens
GROUP BY
String
;
这是一个SQL-Server版本
CREATE TABLE #TempTable (String VARCHAR(100))
INSERT INTO #TempTable (String) VALUES ('mississsipisssss')
INSERT INTO #TempTable (String) VALUES ('ssasdfs')
;WITH cteTokens (String, IndexNum, Token, CharCount) AS (
SELECT
t.String
,1 as IndexNum
,SUBSTRING(t.String,1,1) as Token
,CASE WHEN SUBSTRING(t.String,1,1) = 's' THEN 1 ELSE 0 END As CharCount
FROM
#TempTable t
UNION ALL
SELECT
t.String
,IndexNum + 1 as IndexNum
,SUBSTRING(t.String,IndexNum + 1,1) as Token
,CASE WHEN SUBSTRING(t.String,IndexNum + 1,1) = 's' THEN t.CharCount + 1 ELSE 0 END As CharCount
FROM
#TempTable s
INNER JOIN cteTokens t
ON s.String = t.String
AND LEN(s.String) >= t.IndexNum + 1
)
SELECT
String
,MAX(CharCount)
FROM
cteTokens
GROUP BY
String
它是一个Recursive Common Table Expression [CTE]
,它按照索引位置的顺序将字符串拆分为字符标记,并测试它们是否是您想要的字符。如果令牌是角色,那么它建立在前一个令牌上的计数的基础上,如果是角色,那么你所要做的就是取结果的MAX()
并得到答案。
答案 1 :(得分:1)
这是使用分层查询的标准解决方案。当输入字符串为“null”时,外部查询中的CASE表达式需要给出答案“null”(否则答案将为0,而不应该是)。我没有添加ORDER BY子句 - 如果需要,您可以这样做。祝你好运!
with
inputs ( str ) as (
select 'mississsipisssss' from dual union all
select null from dual union all
select 'stress' from dual union all
select 'alphabeta' from dual
),
prep ( str, lvl ) as (
select str, level
from inputs
connect by prior str = str
and prior sys_guid() is not null
and regexp_instr(str, 's{' || to_char(level-1) || '}') != 0
)
select str, case when str is not null then max(lvl) - 1 end as max_len
from prep
group by str
;
STR MAX_LEN
---------------- ----------
(null) (null)
alphabeta 0
stress 2
mississsipisssss 5
4 rows selected.
答案 2 :(得分:0)
这不是数据库支持的操作,尽管Postres肯定在这个领域有功能。
如果您知道" s" s的子串数量有限制,那么您可以这样做:
select greatest(coalesce(length(regexp(substr(string, '[s]+', 1, 1)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 2)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 3)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 4)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 5)), 0),
coalesce(length(regexp(substr(string, '[s]+', 1, 6)), 0)
)
这将找到前6个子串,然后计算最大长度。
替代方案主要是使用connect by
或递归CTE自行拆分字符串。但是,上述内容可能就足够了。