【问题标题】:PostgreSQL Substring pattern with spacesPostgreSQL 带空格的子串模式
【发布时间】:2026-02-05 21:35:01
【问题描述】:

我一直在努力解决这个问题,尝试在这个论坛中找到解决方案,但我无法继续。我需要帮助。 我有一列存储船舶名称贯穿船舶的生命,我想将它们分成三列。 主要是我有这三个选项,

a) 只有一个名字

select t2.esp1,t2.espectro,t2.espectro1, t2.id from(
select substring(t.espectro, t.posfin)::varchar as esp1, t.espectro,t.espectro1,t.id from(
select "Id" as id, strpos(shipname, ', ') as posinic, strpos(shipname, ' y ') as posfin,shipname as espectro, shipname1 as espectro1 from ships) t)t2 (esp1, espectro, espectro1, id)
where t2.esp1 not like '% y %'`)

b) 两个名字

select t2.esp1,t2.espectro,t2.espectro1, t2.id from(
select substring(t.espectro,1, t.posfin)::varchar as esp1, t.espectro,t.espectro1,t.id from(
select "Id" as id, strpos(shipname, ', ') as posinic, strpos(shipname ' y ') as posfin,shipname as espectro, shipname1 as espectro1 from ships) t)t2 (esp1, espectro, espectro1, id)
where t2.esp1 not like '%, %'`) and for the second name (`select t2.esp1,t2.espectro,t2.espectro1, t2.id from(
select substring(t.espectro, t.posfin)::varchar as esp2, t.espectro,t.espectro2,t.id from(
select "Id" as id, strpos(shipname, ', ') as posinic, strpos(shipname, ' y ') as posfin,shipname as espectro, shipname2 as espectro2 from ships) t)t2 (esp2, espectro, espectro2, id)
where t2.esp2 like '% y %' and t2.espectro not like '%, %';

和c)三个名字:我可以得到第一个

select substring(t.espectro,1,t.posicion) from(
select strpos(shipname, ',') as posicion,shipname as espectro from ships) t;` and third `select t2.esp3,t2.espectro,t2.espectro3, t2.id from(
select substring(t.espectro, t.posfin)::varchar as esp3, t.espectro,t.espectro3,t.id from(
select "Id" as id, strpos(shipname, ', ') as posinic, strpos(shipname, ' y ') as posfin,shipname as espectro, shipname3 as espectro3 from ships) t)t2 (esp3, espectro, espectro3, id)
where t2.esp3 like '% y %' and t2.espectro like '%, %';

但不是第二个

三个命名记录如下所示:

Nuestra Señora del Rosario, Santo Domingo y San José

我已经尝试过这个选项:

select substring(t.shipsnames from '%#",_y#"%' for '#') as name2 from ships t

在#"pattern#" 中进行了几处更改,以查找空格并获取第二个名称。 然后我尝试了这个选项:

select t2.name2[6:7] from (regexp_split_to_array(t.shipnames, E'\\s+') as name2 from ships t) t2

但它不起作用,因为不是每条记录都具有相同的长度,因此有些记录像 {"Santo","Domingo"} 解决,而另一些则不像 {"Rosario",","}。 我不熟悉正则表达式 sintax,我在 PostgreSQL 文档中找到了这个示例。有什么提示吗?

【问题讨论】:

  • 如果您需要同时使用空格和逗号进行拆分,请尝试E'[\\s,]+'
  • 您到底想达到什么目标?当Nuestra Señora del Rosario, Santo Domingo y San José 被提供为输入时,您希望Nuestra Señora del RosarioSanto DomingoSan José 作为输出吗?如果是,一行三列还是三行一列?您能否提供 a) 和 b) 的解决方案作为示例?
  • @markus-benko 我添加了代码来对我使用的记录进行子串化。它工作得很好。感谢您的反馈
  • 我想在三个不同的列中获得三个名称,因为这三个名称是这艘船在其生命中获得的三个名称。因此,三列 name1、name2、name3 并将每个名称存储在那里。

标签: sql regex postgresql substring


【解决方案1】:

如果名称应该被拆分,只要它们被 comma 加上可选的空格或被强制空格包围的 y 分隔,以下正则表达式将起作用:

\s*,\s*|\s+y\s+

\s:空白字符,+:至少一个,*:零个或多个,| 表示交替。

使用此正则表达式的示例 SQL:

SELECT Id, ShipNamesArray[1] ShipName1, ShipNamesArray[2] ShipName2, ShipNamesArray[3] ShipName3
FROM (
    SELECT Id, regexp_split_to_array(Shipnames, '\s*,\s*|\s+y\s+') ShipNamesArray
    FROM (VALUES
        (1, 'Nuestra Señora del Rosario, Santo Domingo y San José'),
        (2, 'Nuestra Señora del Rosario y Santo Domingo'),
        (3, 'Nuestra Señora del Rosario')
    ) AS ExampleShipNames (Id, ShipNames)
) AS SplitShipNames

SQL 将产生以下输出:

Id | ShipName1                  | ShipName2     | ShipName3
-- | -------------------------- | ------------- | ---------
 1 | Nuestra Señora del Rosario | Santo Domingo | San José
 2 | Nuestra Señora del Rosario | Santo Domingo |
 3 | Nuestra Señora del Rosario |               |

【讨论】:

  • 嗨!感谢您的反馈。我试过你的解决方案,至少对我来说它失败了。它不会在\s+y\s+ 之间拆分名称并删除s 字符。我已将代码改进为'\,\s*|\s*y\s*'。但现在我有一个新问题。有一些名称,例如 Nuestra señora de los ReyesSan Cayetano,它们被拆分为,因为代码并不完美。我尝试了几个选项,例如\,\s+|\s*y\s+ 和其他组合。但它仍然不起作用如果没有其他解决方案,你的很好,只需要一点清洁工作,所以提前谢谢!
  • 当您按原样从答案 1:1 执行 SQL 时,您没有得到预期的输出吗?你会得到什么?正则表达式不会删除 s 字符。可能是复制粘贴有问题还是理解有误?
  • Id|ShipName1|Shipname2|Shipname31|Nuestra Señora del Rosario| Santo Domingo y San José|"" 2|Nuestra Señora del Rosario y Santo Domingo|""|"" 3|Nuestra Señora del Rosario|""|"" 这是我得到的回复。我在此服务器中使用 Postgres 8.3,这可能是个问题吗?
  • 好的,所以它按我的预期工作,但不幸的是我当时一定完全误解了你的问题。您能否更详细地解释一下您想要获得的输入和输出,可能是通过显示一个完整示例?
  • 嗨!我认为您没有误解这个问题,您的预期输出正是我所需要的。问题是西班牙语名字很棘手,有很多奇怪的字符。输入就是我解释的,一个文本字段,其名称通常只有一个名称,然后是两个名称,由' y ' 分隔,最后是三个名称,由, 分隔,最后是一个' y '。我想将此字段拆分为三个单独的字段,每个名称一个。正如您所建议的,它可以工作,但 y 在西班牙语中很棘手,例如 Reyes, Cayetano, Rey, etc. 感谢您的反馈。