POSTGRESQL如何将子表的行插入父表的数组中

时间:2018-09-02 18:41:51

标签: sql postgresql

我有2个相关表格:问题和答案

问题

CREATE TABLE questions (
    id SERIAL PRIMARY KEY,
    title TEXT,
    answer_ids INTEGER[]
);

答案

CREATE TABLE answers (
    answer_id SERIAL PRIMARY KEY,
    question_id INTEGER
        REFERENCES questions,
    body TEXT
);

当前实施:

当将一行添加到答案表时,我将答案的answer_id推送到相应行中问题表的answer_ids数组中。即

如果添加了对answer_id = 5问题的回答id = 1。我会做类似

UPDATE questions SET answer_ids = ARRAY_APPEND(answer_ids, 5) WHERE id = 1;

我要实现的目标:

我不一定要寻找一种将答案添加到问题表中的方法,因为我认为这是多余的,那么拥有答案表的意义何在?

我正在寻找一个查询,该查询使我可以提出一个问题,但我希望得到一个answer_ids本身的数组,而不是得到一个answers的数组。因此查询将在JSON中返回类似这样的内容:

{ id: 1,
  title: 'title of question 1',
  answers: [{ answer_id: 1,
              question_id: 1,
              body: 'body of answer 1'},
            { answer_id: 3,
              question_id: 1,
              body: 'body of answer 3'}]
}

2 个答案:

答案 0 :(得分:3)

可能是这个吗? (here are functions for work with json

WITH Questions(id, title) as (
    select 1, 'title 1' union all
    select 2, 'title 2' 
),
Answers(answer_id, question_id, body) as (
    select 1, 1, 'body of answer 1' union all
    select 3, 1, 'body of answer 3'  union all
    select 4, 2, 'body of answer 4'  
)

SELECT json_build_object('id',id, 'title',title, 'answers', 
    (SELECT json_agg(json_build_object('answer_id',answer_id,'question_id',question_id,'body',body)) FROM Answers WHERE Answers.question_id = Questions.id) ) 
from Questions 
WHERE Questions.id = 1

答案 1 :(得分:1)

为n个答案创建类型。

CREATE TYPE answer_t
            AS (answer_id integer,
                question_id integer,
                body text);

然后将answer_id与问题横向交叉连接,并使用它们内部连接答案。现在汇总并使用array_agg()来获得每个问题的答案数组。

SELECT q.*,
       array_agg((a.answer_id,
                  a.question_id,
                  a.body)::answer_t) answers
       FROM questions q
            CROSS JOIN LATERAL unnest(q.answer_ids) un(answer_id)
            INNER JOIN answers a
                       ON a.answer_id = un.answer_id
       GROUP BY q.id;

但是请注意,您的数据设计太糟糕了,应该修改。引用其他记录的值绝不能放在数组中。如果引用完整性位于数组中,则无法强制执行引用完整性,或者仅使用效率非常低的触发器才能强制执行引用完整性。使用链接表。然后,您也可以将后退引用列退回到question_id中的列answers