mysql - 是否有一种优雅且高效的 SQL 方式来列出所有子字符串位置?

标签 mysql sql substring full-text-search

我在 SQL 数据库中有一个文本列。我的任务是查找文本中给定字符串的所有出现位置,并按文本列出字符位置(以便稍后在应用程序中进行反向引用)。

我找到了类似 this 的例子通过 while 循环解决类似的问题。但是,我不喜欢编写循环的想法,因为存在一种更简洁的方法可以做到这一点。

我想这与STRING_SPLIT in T-SQL类似。 ,尽管我强调我最好是在寻找 MySQL 解决方案。 STRING_SPLIT 返回一个一列表,其中填充了分割字符串的子字符串。想象中的 ALL_POSITIONS 方法可以返回一个单列表,其中填充了文本中匹配项的起始位置,如果没有匹配项,则返回一个空表。或者,为了连接,可能还有另一列用于主键引用。

所以让我们用一个示例表格来说明我的观点:

|Id|Text                      |
+--+--------------------------+
| 0|This is my teststring     |
| 1|A second teststring       |

我梦想的伪SQL:

从表中选择 ALL_POSITIONS('st', Text, Id);

这会产生:

|Id|Position|
+--+--------+
| 0|      13|    <- the first 'st' where Id = 0
| 0|      15|    <- the second 'st' where Id = 0 etc.
| 1|      11|
| 1|      13|

欢迎任何想法。

最佳答案

使用 SQL Server 的递归 CTE:

with cte as (
  select id, charindex('st', text) pos from tablename
  union all
  select t.id, charindex('st', t.text, c.pos + 1) 
  from tablename t inner join cte c
  on c.id = t.id
  where c.pos > 0 and c.pos < len(t.text)
)
select * from cte
where pos > 0
order by id, pos

请参阅demo .
对于 MySql 8.0+:

with recursive cte as (
  select id, locate('st', text) pos from tablename
  union all
  select t.id, locate('st', t.text, c.pos + 1) 
  from tablename t inner join cte c
  on c.id = t.id
  where c.pos > 0 and c.pos < length(t.text)
)
select * from cte
where pos > 0
order by id, pos

请参阅demo .
结果:

> id | pos
> -: | --:
>  0 |  14
>  0 |  16
>  1 |  12
>  1 |  14

关于mysql - 是否有一种优雅且高效的 SQL 方式来列出所有子字符串位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58803732/

相关文章:

sql - select * from table1 that does not exist in table2 with conditional

python - 为什么我的 Python 元组只存储第一个值?

mysql - 多列上的数据透视样式计算

java - 带子串的for循环

mysql - 如何使用 YII2 关系求和 hasMany?

php - 命令不同步;你现在不能运行这个命令

sql - Postgres 约束和外键

mysql - PHP : Parse all data from mysql where the 3rd and 4th digit of the id

string - 较长字符串中最长重复字符串的长度

sql - 如何将数据从谷歌数据存储实体下载到本地?