Mysql 从一个字符串中的(多个)方括号中提取值
下面是我想用MySQL(MariaDB)做的事情。我想在“Case_Title”列中的花括号(我们称之为标记)之间检索内容的子字符串。我的桌子看起来像这样 表格:案例Mysql 从一个字符串中的(多个)方括号中提取值,mysql,sql,Mysql,Sql,下面是我想用MySQL(MariaDB)做的事情。我想在“Case_Title”列中的花括号(我们称之为标记)之间检索内容的子字符串。我的桌子看起来像这样 表格:案例 | Case_ID | Case_Title | Department | |---------|----------------------------------|-------------| | 7032389 | {RJ1} Not able to connect
| Case_ID | Case_Title | Department |
|---------|----------------------------------|-------------|
| 7032389 | {RJ1} Not able to connect | Consumer |
| 7243040 | {RJ2}{ZO}{WAD} Connection issues | Business |
| 7249910 | {O2A} No incoming mgs {WAD} | Consumer |
|---------|----------------------------------|-------------|
通过搜索堆栈溢出,我找到了两个选项来检索这些子字符串
1-使用正则表达式。因为我在MariaDB上,所以我可以使用REGEXP\u SUBSTR、REGEXP\u INSTR、REGEXP\u REPLACE
2-SUBSTR()和INSTR()的组合。
SELECT Case_ID, SUBSTR(Case_Title,INSTR(Case_Title,"{"), INSTR(Case_Title,"}") - INSTR(Case_Title,"{") + 1) as 'Tag'
FROM cases
两个选项都将输出:
| Case_ID | Tag |
|---------|-------|
| 7032389 | {RJ1} |
| 7243040 | {RJ2} |
| 7249910 | {O2A} |
|---------|-------|
但是,案例标题中的其他“标记”将被忽略。我似乎找不到一种方法来获得这样的输出:
| Case_ID | Tag |
|---------|-------|
| 7032389 | {RJ1} |
| 7243040 | {RJ2} |
| 7243040 | {ZO} |
| 7243040 | {WAD} |
| 7249910 | {O2A} |
| 7249910 | {WAD} |
|---------|-------|
请注意,我希望每个标记都有新的记录/行,而不是像这样连接它们:{RJ1}、{ZO}、{WAD}
。另外,我事先不知道:
- 一个标题将包含多少个标记
- 标签位于案例标题中的位置
- 如果所有标记都分组在一起或分散在案例标题中
- 标签本身的实际内容
}{
分隔数据,然后在自己的行中获取每个值。从那里我删除了第一个}
之后的所有值。需要进行一些连接以恢复在旋转过程中删除的丢失括号
SELECT Case_ID,
CONCAT(substring_index(CASE WHEN RIGHT(CASE WHEN LEFT(tag,1) = '{'
THEN tag
ELSE CONCAT('{',tag) END,1) = '}'
THEN CASE WHEN LEFT(tag,1) = '{'
THEN tag
ELSE CONCAT('{',tag)
END
ELSE CONCAT(CASE WHEN LEFT(tag,1) = '{'
THEN tag
ELSE CONCAT('{',tag)
END,'}')
END,'}',1),'}') AS tag
FROM (
SELECT DISTINCT Case_ID, SUBSTRING_INDEX(SUBSTRING_INDEX(Case_Title, '}{', n), '}{', -1) tag
FROM (SELECT 1 n
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5) n
INNER JOIN cases ON CHAR_LENGTH(Case_Title)-CHAR_LENGTH(REPLACE(Case_Title, '}{', ''))>=n-1) a
输入
输出
Case_ID tag
7032389 {RJ1}
7243040 {RJ2}
7249910 {O2A}
7243040 {ZO}
7243040 {WAD}
SQL Fiddle:使用函数组合,首先旋转数据,用
}{
分隔数据,然后在自己的行中获取每个值。从那里我删除了第一个}
之后的所有值。需要进行一些连接以恢复在旋转过程中删除的丢失括号
SELECT Case_ID,
CONCAT(substring_index(CASE WHEN RIGHT(CASE WHEN LEFT(tag,1) = '{'
THEN tag
ELSE CONCAT('{',tag) END,1) = '}'
THEN CASE WHEN LEFT(tag,1) = '{'
THEN tag
ELSE CONCAT('{',tag)
END
ELSE CONCAT(CASE WHEN LEFT(tag,1) = '{'
THEN tag
ELSE CONCAT('{',tag)
END,'}')
END,'}',1),'}') AS tag
FROM (
SELECT DISTINCT Case_ID, SUBSTRING_INDEX(SUBSTRING_INDEX(Case_Title, '}{', n), '}{', -1) tag
FROM (SELECT 1 n
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5) n
INNER JOIN cases ON CHAR_LENGTH(Case_Title)-CHAR_LENGTH(REPLACE(Case_Title, '}{', ''))>=n-1) a
输入
输出
Case_ID tag
7032389 {RJ1}
7243040 {RJ2}
7249910 {O2A}
7243040 {ZO}
7243040 {WAD}
SQL Fiddle:我没有时间把这作为完整的答案,但请考虑:将您的表连接到另一个表,该表只是一个数字列表1、2、3、4、5、6。。。(你可以通过联盟来实现)。使join的ON子句成为
number
所在的谓词,并使用您的正则表达式匹配方法-它只拾取每行找到的第一个字段,因此在第一、第二、第三个子字符串索引上剪切字符串(出现){,要在正则表达式看到值之前从第二行、第三行等中删除字段,..pps;您需要的行数与最大字段数一样多..因此,如果您的一个案例标题有450个字段,您需要450个数字,该行必须重复450次..诸如此类对于我们这些不是天才诺玛的人来说理顺我们的数据库。让有价值的客户数据服从天才的奇思妙想并不是真正合乎道德的。尽管如此,请阅读本文。它解释了如何提取逗号分隔的值。您可以根据您的{}
tags。我没有时间完整回答这个问题,但请考虑:将您的表连接到另一个表,该表只是一个数字列表1、2、3、4、5、6…(您可以通过并集实现).使join的ON子句成为数字
所在的谓词,并使用您的正则表达式匹配方法-它只拾取每行找到的第一个字段,因此在第1、第2、第3个子字符串索引上剪切字符串(出现){,要在正则表达式看到值之前从第二行、第三行等中删除字段,..pps;您需要的行数与最大字段数一样多..因此,如果您的一个案例标题有450个字段,您需要450个数字,该行必须重复450次..诸如此类对于我们这些不是天才诺玛的人来说lize我们的数据库。让有价值的客户数据服从天才的奇思妙想并不是真正合乎道德的。尽管如此,请阅读本文。它解释了如何提取逗号分隔的值。您可以将其调整为您的{}
标记。除了Case_ID 7249910之外,它工作起来很有魅力。它只输出{O2A},而忽略{WAD}原因是它只在'}{'
处拆分字符串。因此,我首先使用REGEXP_REPLACE(case_title'}(.*?{','}{')更改字符串。
除了case_ID 7249910之外,工作起来就像一个符咒。它只输出{O2A},而忽略{WAD}原因是它只在'}{'
处拆分字符串。因此,我首先使用REGEXP\u REPLACE(case\u title,'}(.?{','}{')