Mysql 从一个字符串中的(多个)方括号中提取值

Mysql 从一个字符串中的(多个)方括号中提取值,mysql,sql,Mysql,Sql,下面是我想用MySQL(MariaDB)做的事情。我想在“Case_Title”列中的花括号(我们称之为标记)之间检索内容的子字符串。我的桌子看起来像这样 表格:案例 | Case_ID | Case_Title | Department | |---------|----------------------------------|-------------| | 7032389 | {RJ1} Not able to connect

下面是我想用MySQL(MariaDB)做的事情。我想在“Case_Title”列中的花括号(我们称之为标记)之间检索内容的子字符串。我的桌子看起来像这样

表格:案例

| 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,'}(.?{','}{')