PostgreSQL 11中基于模式匹配的字符串数据提取通用查询需求
PostgreSQL 11 通用子串提取查询解决方案
需求场景
需要从多种格式的文本中提取指定子串,核心是提取|a后和|d后的目标内容,无|a时提取文本开头的对应内容。以下是具体示例与提取规则:
示例输入与期望输出
- 示例1:输入
"|a john dumas .|d 1941|e united states|=^A22306",期望输出john dumas .1941 - 示例2:输入
"|a john dumas .|e united states|=^A22306",期望输出john dumas . - 示例3:输入
"|a john dumas .|=^A22306 |e united states |d 1941 |f admin ",期望输出john dumas .1941 - 示例4:输入
"|a john dumas .|f admin |d 1941 |=^A22306 |e united states",期望输出john dumas .1941 - 示例5:输入
"|a john dumas .|f admin |d 1941 ",期望输出john dumas .1941 - 示例6:输入
"|a john dumas . ",期望输出john dumas . - 示例7:输入
"john dumas .|e united states |d 1941 ",期望输出john dumas .1941 - 示例8:输入
"john dumas .",期望输出john dumas .
提取规则
- 若文本包含
|a,读取|a到第一个|之间的内容;若同时包含|d,读取|d到其后第一个|之间的内容 - 若文本包含
|a和|d,且|d后无|,读取|d到文本末尾的内容 - 若文本包含
|a且|a后无|,读取|a到文本末尾的内容 - 若文本包含
|a但无|d,读取|a到第一个|之间的内容 - 若文本不含
|a,读取文本开头到第一个|之间的内容;若同时包含|d且|d后无|,读取|d到文本末尾的内容 - 若文本不含
|a且无|,读取全部文本内容
现有尝试问题
之前的查询仅能处理部分示例:
select replace(substring('|a john dumas .|d 1941|e united states|=^A22306' from '\|a(.+)\|e'), '|d', '')
输出为" john dumas . 1941",无法覆盖所有场景。
通用解决方案
以下SQL查询可处理所有示例场景:
SELECT TRIM( CONCAT( -- 提取主内容:有|a则取|a到第一个|,无则取开头到第一个|或全部 CASE WHEN str LIKE '%|a%' THEN COALESCE( SUBSTRING(str FROM '\|a\s*(.*?)(?=\||$)'), SUBSTRING(str FROM '\|a\s*(.*)') ) ELSE COALESCE( SUBSTRING(str FROM '^(.*?)(?=\||$)'), str ) END, -- 提取|d后的内容:存在则追加 CASE WHEN str LIKE '%|d%' THEN COALESCE( SUBSTRING(str FROM '\|d\s*(.*?)(?=\||$)'), SUBSTRING(str FROM '\|d\s*(.*)') ) ELSE '' END ) ) AS extracted_content FROM ( -- 测试所有示例输入 VALUES ('|a john dumas .|d 1941|e united states|=^A22306'), ('|a john dumas .|e united states|=^A22306'), ('|a john dumas .|=^A22306 |e united states |d 1941 |f admin '), ('|a john dumas .|f admin |d 1941 |=^A22306 |e united states'), ('|a john dumas .|f admin |d 1941 '), ('|a john dumas . '), ('john dumas .|e united states |d 1941 '), ('john dumas .') ) AS test_data(str);
代码解释
- 主内容提取:通过
CASE判断是否含|a,使用非贪婪正则.*?匹配到第一个|,若|a后无|则用.*匹配到末尾;无|a时同理取开头到第一个|或全部内容。 - |d内容追加:同样用正则匹配
|d后的内容,存在则追加到主内容后。 - TRIM函数:去除结果两端的冗余空格,保证输出整洁。
执行上述查询后,所有示例均可得到符合预期的输出。
内容的提问来源于stack exchange,提问作者franco
相关产品推荐
相关产品推荐

