You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 .

提取规则

  1. 若文本包含|a,读取|a到第一个|之间的内容;若同时包含|d,读取|d到其后第一个|之间的内容
  2. 若文本包含|a和|d,且|d后无|,读取|d到文本末尾的内容
  3. 若文本包含|a且|a后无|,读取|a到文本末尾的内容
  4. 若文本包含|a但无|d,读取|a到第一个|之间的内容
  5. 若文本不含|a,读取文本开头到第一个|之间的内容;若同时包含|d且|d后无|,读取|d到文本末尾的内容
  6. 若文本不含|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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 17:12:47