【问题标题】:How to split array data to next row in Postgres如何将数组数据拆分到 Postgres 中的下一行
【发布时间】:2023-01-17 17:43:50
【问题描述】:

我有一个表中的数据。我想将数组数据拆分成单独的行。

create table test1 (
  _id serial, 
  questionId character varying (50), 
  answer character varying (50), 
  subquestionId character varying (50), 
  subquestionAnswer character varying (50), 
  isActive character varying (1)
);

INSERT INTO test1 (questionid,answer,subquestionid,subquestionanswer,isactive) 
values 
('question 1','true','[100,101,102]','[[true],[false],[true]]','1'),('question 2','false','[101,106]','[[false],[true]]','1');
_id questionid answer subquestionid subquestionanswer isactive
1 question 1 true [100,101,102] [[true],[false],[true]] 1
2 question 2 false [101,106] [[false],[true]] 1

应该需要输出。

【问题讨论】:

  • isActive 应该是booleansubquestionidsubquestionanswer 应该规范化为一对多关系。但至少这些列应该是 text[] 或者可能组合成一个 jsonb,其中 ID 是键,标志是值。
  • 你能用样本输入表更新你的帖子吗?
  • 输出在链接中不可用。请在问题正文中分享。

标签: sql postgresql


【解决方案1】:

this answer 中所述,您可以使用转换和转换将数组的字符串表示形式转换为实际数组。 (正如评论你应该不是将数组存储为字符串)

select 
   _id, 
   answer,
   translate(subquestionid, '[]', '{}')::int[] subquestionid,
   translate(subquestionanswer, '[]', '{}')::boolean[] subquestionanswer, 
   isactive
from test1;

结果

_id|answer|subquestionid|subquestionanswer      |isactive|
---+------+-------------+-----------------------+--------+
  1|true  |{100,101,102}|{{true},{false},{true}}|1       |
  2|false |{101,106}    |{{false},{true}}       |1       |

要拆分数组,请使用 unnest 并使用 WITH ORDINALITY AS 保持顺序

Finaly 将结果限制为具有相同ordinality 的行,我认为这是预期的结果,尽管与您的输出不同

with t as (
select 
   _id, 
   answer,
   translate(subquestionid, '[]', '{}')::int[] subquestionid,
   translate(subquestionanswer, '[]', '{}')::boolean[] subquestionanswer, 
   isactive
from test1
)  
select   
 t._id, 
 t.answer,
 a.subquestionid, 
 b.subquestionanswer,
 t.isactive
from t
cross join lateral unnest(subquestionid) WITH ORDINALITY AS a(subquestionid, nr)
cross join lateral unnest(subquestionanswer) WITH ORDINALITY AS b(subquestionanswer, nr)
where a.nr = b.nr


_id|answer|subquestionid|subquestionanswer|isactive|
---+------+-------------+-----------------+--------+
  1|true  |          100|true             |1       |
  1|true  |          101|false            |1       |
  1|true  |          102|true             |1       |
  2|false |          101|false            |1       |
  2|false |          106|true             |1       |

【讨论】:

  • 以下格式的数据出现错误。插入查询新数据。 INSERT INTO test1 (questionid,answer,subquestionid,subquestionanswer,isactive) values ('question 3','true','[151,152,153,154]','[["option1"],["option1"],["option1", “选项 2”],[“选项 3”]]','1');
  • 这值得提出一个新问题以及您对 153 的输出期望什么的解释 - 一行或两行? @Srk
【解决方案2】:

您可以使用 string_to_array 将字符串转换为数组,并从单行生成多行,如下所示:

SELECT *
FROM (
  SELECT t._id, t.questionid, t.answer, REGEXP_REPLACE(theAnswer, '[|]|[[|]]', '') as subquestionanswer, t.isactive
  FROM   test1 t, 
       unnest(string_to_array(subquestionanswer, '],[')) theAnswer
  ) S

这应该是这样的:

SELECT t._id, t.questionid, t.answer, s.subquestionid, t.subquestionanswer, t.isactive
FROM (
  SELECT _id, questionid, answer, REGEXP_REPLACE(subquestionans, '[|]|[[|]]', '') as subquestionanswer, isactive,
  ROW_NUMBER () OVER (
           ORDER BY _id
        )
  FROM   test1, 
       unnest(string_to_array(subquestionanswer, '],[')) subquestionans
) t
inner join (
  SELECT _id , REGEXP_REPLACE(subquestion, '[|]', '') as subquestionid,
  ROW_NUMBER () OVER (
           ORDER BY _id
        )
  FROM  test1 , 
       unnest(string_to_array(subquestionid, ',')) subquestion
) s on s.ROW_NUMBER = t.ROW_NUMBER;

演示在这里:https://dbfiddle.uk/b1w3RyCJ

【讨论】:

  • 好吧,unnest 确实保证保留顺序,但与未嵌套表的连接不会,因此对于更大的示例,您可能会弄乱 row_number 中的行顺序(with ordinaltiy 是为此目的发明的 - 请参阅另一个答案)
【解决方案3】:

感谢您的答复!

下表数据需要转换成截图格式。以前是一括号一值,现在是一括号二值。 (subquestionid-153)。我已经从 Talend 中提取了这些数据。

create table test1 (_id serial, questionId character varying (50), answer character varying (50), subquestionId character varying (50), subquestionAnswer character varying (225), isActive character varying (1));

INSERT INTO test1 (questionid,answer,subquestionid,subquestionanswer,isactive) values ('question 1','true','[100,101,102]','[[true],[false],[true]]','1'),('question 2','false','[101,106]','[[false],[true]]','1');

【讨论】:

    猜你喜欢
    • 2019-02-06
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 2022-12-04
    • 1970-01-01
    • 2021-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多