使用 SQL 。从字符串'HEADER|N1000|E1001|N1002|E1003|N1004|N1005'中提取逗号分隔的数字

Posted

技术标签:

【中文标题】使用 SQL 。从字符串\'HEADER|N1000|E1001|N1002|E1003|N1004|N1005\'中提取逗号分隔的数字【英文标题】:USING SQL . extract numbers comma separated from string 'HEADER|N1000|E1001|N1002|E1003|N1004|N1005'使用 SQL 。从字符串'HEADER|N1000|E1001|N1002|E1003|N1004|N1005'中提取逗号分隔的数字 【发布时间】:2019-10-14 04:28:15 【问题描述】:
'HEADER|N1000|E1001|N1002|E1003|N1004|N1005'    
   'HEADER|N156|E1|N7|E122|N4|E5'   
   'HEADER|E0|E1|E2|E3|E4|E5'   
   'HEADER|N0|N1|N2|N3|N4|N5'
   'HEADER|N125' 

如何从这个字符串中提取逗号分隔格式的数字?

预期结果:

1000,1001,1002,1003,1004,1005

如何提取以 N 或 E 作为后缀/前缀的数字,即。

N1000 

预期结果:

1000,1002,1004,1005

下面的正则表达式不会返回所需的结果。但我想要这样的东西

select REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005', '.*?(\d+)', '\1,'), ',?\.*$', '') from dual

这里的问题是 当我想要带有 E OR N 的数字时

select REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005', '.*?N(\d+)', '\1,'), ',?\.*$', '') from dual
select REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005', '.*?E(\d+)', '\1,'), ',?\.*$', '') from dual

他们为这个场景提供了很好的结果

但是当我输入'HEADER|N1000|E1001'时它给出了错误的答案请验证并更正它

【问题讨论】:

【参考方案1】:

更新

根据对问题的更改,原始答案无效。相反,解决方案要复杂得多,使用分层查询从字符串中提取所有数字,然后使用LISTAGG 将从每个字符串中提取的数字列表重新组合在一起。要提取所有数字,我们使用以下查询:

WITH cte AS (
  SELECT DISTINCT data, level AS l, REGEXP_SUBSTR(data, '[NE]\d+', 1, level) AS num FROM test
  CONNECT BY REGEXP_SUBSTR(data, '[NE]\d+', 1, level) IS NOT NULL
)
SELECT data, LISTAGG(SUBSTR(num, 2), ',') WITHIN GROUP (ORDER BY l) AS "All numbers"
FROM cte
GROUP BY data

输出(用于新的样本数据):

DATA                                        All numbers
HEADER|E0|E1|E2|E3|E4|E5                    0,1,2,3,4,5
HEADER|N0|N1|N2|N3|N4|N5                    0,1,2,3,4,5
HEADER|N1000|E1001|N1002|E1003|N1004|N1005  1000,1001,1002,1003,1004,1005
HEADER|N125                                 125
HEADER|N156|E1|N7|E122|N4|E5                156,1,7,122,4,5

要仅选择以E 开头的数字,我们修改查询以仅将REGEXP_SUBSTR 表达式中的[EN] 替换为E,即

  SELECT DISTINCT data, level AS l, REGEXP_SUBSTR(data, 'E\d+', 1, level) AS num FROM test
  CONNECT BY REGEXP_SUBSTR(data, 'E\d+', 1, level) IS NOT NULL

输出:

DATA                                        E-numbers
HEADER|E0|E1|E2|E3|E4|E5                    0,1,2,3,4,5
HEADER|N0|N1|N2|N3|N4|N5    
HEADER|N1000|E1001|N1002|E1003|N1004|N1005  1001,1003
HEADER|N125     
HEADER|N156|E1|N7|E122|N4|E5                1,122,5

可以进行类似的更改以提取以N 开头的数字。

Demo on dbfiddle

原答案

实现您想要的结果的一种方法是用该数字和逗号替换导致数字的字符串,然后将结果中最后一个 ,| 到字符串末尾的任何字符替换为:

SELECT REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '.*?(\d+)', '\1,'), ',?\|.*$', '') FROM dual

输出:

1000,1001,1002,1003,1004,1005

为了只输出以N 开头的数字,我们将其添加到捕获组之前的前缀字符串中:

SELECT REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '.*?N(\d+)', '\1,'), ',?\|.*$', '') FROM dual

输出:

1000,1002,1004,1005

为了只输出以E 开头的数字,我们将其添加到捕获组之前的前缀字符串中:

SELECT REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '.*?E(\d+)', '\1,'), ',?\|.*$', '') FROM dual

输出:

1001,1003

Demo on dbfiddle

【讨论】:

评论不适用于扩展讨论或调试会话;这个对话是archived in chat。 @nick 我已经添加了新的数据集。查询应该满足这些数据集 @amarenderreddyjali 我已经更新了我的答案。它现在应该更加健壮(并且适用于您给出的所有示例) @nick 谢谢,但我正在考虑使用你以前的答案和 ''' select * from (SELECT REGEXP_REPLACE(REGEXP_REPLACE('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '.*?E(\d+)', '\1,'), ',?\|.*$', '') as mum FROM dual) where mum like '%|E% '''【参考方案2】:

我不知道您使用的是什么 DBMS,但这是在 Postgres 中执行此操作的一种方法:

WITH cte AS (
  SELECT CAST('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|' AS VARCHAR(1000)) AS myValue
)
SELECT SUBSTRING(MyVal FROM 2)
FROM (
  SELECT REGEXP_SPLIT_TO_TABLE(myValue,'\|') MyVal
  FROM cte
) src
WHERE SUBSTRING(MyVal FROM 1 FOR 1) = 'N'
;

SQL Fiddle

【讨论】:

【参考方案3】:

据我所了解的问题,您想从字符串中提取以 N 开头的子字符串,您可以尝试以下操作(如果需要,您可以合并以逗号分隔的输出)

select REPLACE(value, 'N', '') from STRING_SPLIT('HEADER|N1000|E1001|N1002|E1003|N1004|N1005|', '|') where value like 'N%'

输出:

1000 1002 1004 1005

【讨论】:

以上是关于使用 SQL 。从字符串'HEADER|N1000|E1001|N1002|E1003|N1004|N1005'中提取逗号分隔的数字的主要内容,如果未能解决你的问题,请参考以下文章

SQL基础

使用 SQL 标量函数的查询如何从 5 分钟内运行到 5 小时

需要批量发送通知 1000

查找从sql查询返回的数组中的项

使用 SQL 查询打印素数

将数据从 XML 导入 SQL Server 表