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

PostgreSQL拆分括号内数据为行时出现空值问题求助

问题描述

在PostgreSQL的test表中存储了以下数据,其中questionid为201的记录对应option_3和option_4,但执行给定查询时,第二条结果的questionid为空,期望能正常显示201。

表结构及初始化数据:

create table test 
(id integer,
questionid character varying (255),
questionanswer character varying (255));

INSERT INTO test (id,questionid,questionanswer) VALUES
     (1,'[101,102,103]','[["option_11"],["KILA ALIPOKUWA ANAUMWA YEYE ALIJUWA NI AROSTO HALI YA KUKOSA KUVUTA MADAWA.."],["option_14"]]'),
     (2,'[201]','[["option_3","option_4"]]');

原查询语句:

SELECT *, 
replace(unnest(string_to_array(translate(questionid, '],[ ', '","'), ',' ))::text,'"','') as questionid,
replace(unnest(string_to_array(translate(questionanswer, '],[ ', '","'), ',' ))::text,'"','') as questionanswer
from test;
问题原因

在SELECT中同时对两个数组执行unnest时,PostgreSQL会按数组元素数量逐行展开。如果两个数组长度不一致(比如id=2的记录中,questionid拆分为1个元素,questionanswer拆分为2个元素),短数组的元素耗尽后,后续行对应的短数组列就会显示为null。

解决方案

可以通过LATERAL JOIN结合generate_series对齐两个数组的元素,确保每个questionanswer元素都能匹配到正确的questionid。以下是修正后的查询:

SELECT 
    t.id,
    -- 若questionid数组长度不足,重复使用第一个元素
    COALESCE(qid.val, qid_list[1]) AS questionid,
    qans.val AS questionanswer
FROM test t
-- 先把questionid转换为数组
CROSS JOIN LATERAL (
    SELECT string_to_array(translate(t.questionid, '[] ', ''), ',') AS qid_list
) qid_arr
-- 拆分questionanswer并生成带索引的行
CROSS JOIN LATERAL (
    SELECT 
        replace(unnest(string_to_array(translate(t.questionanswer, '[] ', ''), ',')), '"', '') AS val,
        generate_series(1, array_length(string_to_array(translate(t.questionanswer, '[] ', ''), ','), 1)) AS idx
) qans
-- 按索引关联questionid的元素
LEFT JOIN LATERAL (
    SELECT 
        replace(unnest(qid_arr.qid_list), '"', '') AS val,
        generate_series(1, array_length(qid_arr.qid_list, 1)) AS idx
) qid ON qid.idx = qans.idx;

也可以用unnest WITH ORDINALITY按位置关联,逻辑更直观:

SELECT
    t.id,
    CASE 
        WHEN qid.idx IS NOT NULL THEN qid.val
        ELSE (SELECT replace(unnest(string_to_array(translate(t.questionid, '[] ', ''), ',')), '"', '') LIMIT 1)
    END AS questionid,
    qans.val AS questionanswer
FROM test t
-- 拆分questionanswer并带上序号
CROSS JOIN LATERAL (
    SELECT 
        replace(unnest(string_to_array(translate(t.questionanswer, '[] ', ''), ',')), '"', '') AS val,
        ordinality AS idx
    FROM unnest(string_to_array(translate(t.questionanswer, '[] ', ''), ',')) WITH ORDINALITY
) qans
-- 拆分questionid并带上序号,按序号关联
LEFT JOIN LATERAL (
    SELECT 
        replace(unnest(string_to_array(translate(t.questionid, '[] ', ''), ',')), '"', '') AS val,
        ordinality AS idx
    FROM unnest(string_to_array(translate(t.questionid, '[] ', ''), ',')) WITH ORDINALITY
) qid ON qid.idx = qans.idx;
效果说明
  • 对于id=1的记录,questionid和questionanswer都拆分为3个元素,会一一对应显示;
  • 对于id=2的记录,questionanswer拆分为2个元素,questionid只有1个,第二个元素会自动复用questionid的201,不会再出现null。

内容的提问来源于stack exchange,提问作者sahil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:15:45