【问题标题】:PostgreSQL: Query that splits array of one element into multiple elements based on a delimiter and unnest itPostgreSQL:根据分隔符将一个元素的数组拆分为多个元素并取消嵌套的查询
【发布时间】:2020-05-15 20:17:07
【问题描述】:

我是 PostgreSQl 的新手,我无法找到获得下面提到的输出的解决方案。

我创建了一个表,其中有一列数据类型为 text[],它是一个文本字符串数组(单个元素)。

我的桌子是这样的:

col1       col2
ID1      {"P25963(MI:0326), Homo sapiens);O14920(MI:0326), Homo sapiens)"}
ID2      {"Q8NFZ0(MI:0326), Homo sapiens);P12931(MI:0326), Homo sapiens)"}
ID3      {"P26368(MI:0326), Homo sapiens);Q15637(MI:0326), Homo sapiens); Q15638(MI:0326), Homo sapiens)"}

当我尝试访问 col2 的第一个和第二个元素时,我得到以下输出。

SELECT col2[1] FROM table;

P25963(MI:0326), Homo sapiens);O14920(MI:0326), Homo sapiens
Q8NFZ0(MI:0326), Homo sapiens);P12931(MI:0326), Homo sapiens
P26368(MI:0326), Homo sapiens);Q15637(MI:0326), Homo sapiens); Q15638(MI:0326), Homo sapiens

SELECT col2[2] FROM table;

NULL
NULL
NULL

我想将此数组元素拆分为多个元素(存在;),将它们取消嵌套,然后对未嵌套的行执行一些正则表达式。

拆分后想要的输出是:

col1       col2
ID1       {P25963(MI:0326), Homo sapiens},{O14920(MI:0326), Homo sapiens}
ID2       {Q8NFZ0(MI:0326), Homo sapiens},{P12931(MI:0326), Homo sapiens}
ID3       {P26368(MI:0326), Homo sapiens},{Q15637(MI:0326), Homo sapiens}, {Q15638(MI:0326), Homo sapiens}

取消嵌套后所需的输出是:

col1     col3                                 col4   
ID1      P25963(MI:0326), Homo sapiens       O14920(MI:0326), Homo sapiens    
ID2      Q8NFZ0(MI:0326), Homo sapiens       P12931(MI:0326), Homo sapiens  
ID3      P26368(MI:0326), Homo sapiens       Q15637(MI:0326), Homo sapiens
ID3      P26368(MI:0326), Homo sapiens       Q15638(MI:0326), Homo sapiens

任何建议都会很有帮助。

谢谢

【问题讨论】:

  • 那么每个数组都包含一个元素?
  • 是的,为了更清晰,我已经编辑了原始帖子

标签: sql arrays string postgresql unnest


【解决方案1】:

我将只访问文本数组中的第一个元素并使用split_part() 来获取基础信息:

select 
    col1,
    split_part(col2[1], ';', 1) col3,
    split_part(col2[1], ';', 2) col4
from mytable

Demo on DB Fiddle

col1 | col3 | col4 :--- | :----------------------------- | :---------------------------- ID1 | P25963(MI:0326),智人) | O14920(MI:0326),智人) ID2 | Q8NFZ0(MI:0326),智人) | P12931(MI:0326),智人) ID3 | P26368(MI:0326),智人) | Q15637(MI:0326),智人)

来自 cmets:如果您想拆分可变数量的元素,我建议将数据分散到行而不是列中。为此,您可以使用string_to_array() 将字符串拆分为数组,然后使用unnest() 生成行:

select
    t.col1,
    s.pos,
    s.val
from mytable t
cross join lateral unnest(string_to_array(t.col2[1], ';')) with ordinality s(val, pos)

Demo

col1 |位置 |值 :--- | --: | :---------------------------- ID1 | 1 | P25963(MI:0326),智人) ID1 | 2 | O14920(MI:0326),智人) ID2 | 1 | Q8NFZ0(MI:0326),智人) ID2 | 2 | P12931(MI:0326),智人) ID3 | 1 | P26368(MI:0326),智人) ID3 | 2 | Q15637(MI:0326),智人) ID3 | 3 | Q15638(MI:0326),智人)

【讨论】:

  • 我可以根据 ; 的存在将数组拆分为 n 个元素吗? ?请参阅 ID3,它有 3 个元素。如果我为 n 个元素这样做会很麻烦
  • @ranusharma:您可以再添加一个split_part() 表达式以获得第三项(请注意,您的预期输出只有两列)。但是,如果您希望它是动态的,那么您宁愿将元素分布在行上而不是列上(SQL 查询必须返回 fixed 列集)。
  • 感谢您的努力。但是我想把它分散在列上。
  • @ranusharma 按什么标准传播?您不能拥有动态列。充其量,使用数组列
猜你喜欢
  • 2020-06-08
  • 2017-06-24
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多