使用自连接在 row_to_json() 中复制 JSON 元素
Duplicate JSON element in row_to_json() with self-join
这是这个优秀问答的后续:13227142。
我几乎不得不做同样的事情(受 PostgreSQL 9.2 的限制)但我只使用了一个 table。因此,查询使用自连接(为了生成正确的 JSON 格式),这会导致重复的 id 字段。我怎样才能避免这种情况?
示例:
CREATE TABLE books
(
id serial primary key,
isbn text,
author text,
title text,
edition text,
teaser text
);
SELECT row_to_json(row)
FROM
(
SELECT id AS bookid,
author,
cover
FROM books
INNER JOIN
(
SELECT id, title, edition, teaser
FROM books
) cover(id, title, edition, teaser)
USING (id)
) row;
结果:
{
"bookid": 1,
"author": "Bjarne Stroustrup",
"cover": {
"id": 1,
"title": "Design and Evolution of C++",
"edition": "1st edition",
"teaser": "This book focuses on the principles, processes and decisions made during the development of the C++ programming language"
}
}
我想删除 "cover" 中的 "id"。
你需要id才能加入,所以没有id你不能做这么短的查询。你需要构造它。像:
select row_to_json(row,true)
FROM
(
with a as (select id,isbn,author,row_to_json((title,edition,teaser)) r from books
)
select a.id AS bookid,a.author, concat('{"title":',r->'f1',',"edition":',r->'f2',',"teaser":',r->'f3','}')::json as cover
from a
) row;
row_to_json
--------------------------------------------------------
{"bookid":1, +
"author":"\"b\"", +
"cover":{"title":"c","edition":"d","teaser":"\"b\""}}
(1 row)
同样,如果没有加入,您使用的资源会减少两倍
事实证明这是一项棘手的任务。据我所知,用一个简单的查询是不可能实现的。
一种解决方案是使用预定义的数据类型:
CREATE TYPE bookcovertype AS (title text, edition text, teaser text);
SELECT row_to_json(row)
FROM
(
SELECT books.id AS bookid, books.author,
row_to_json(row(books.title, books.edition, books.teaser)::bookcovertype) as cover
FROM books
) row;
为了完整起见,我自己偶然发现了另一个答案:可以通过字符串函数消除附加字段。但是,我更喜欢 AlexM 的回答,因为它会更快并且仍然与 PostgreSQL 9.2 兼容。
SELECT regexp_replace(
(
SELECT row_to_json(row)
FROM
(
SELECT id AS bookid,
author,
cover
FROM books
INNER JOIN
(
SELECT id, title, edition, teaser
FROM books
) cover(id, title, edition, teaser)
USING (id)
) row
)::text,
'"id":\d+,',
'')
这是这个优秀问答的后续:13227142。
我几乎不得不做同样的事情(受 PostgreSQL 9.2 的限制)但我只使用了一个 table。因此,查询使用自连接(为了生成正确的 JSON 格式),这会导致重复的 id 字段。我怎样才能避免这种情况?
示例:
CREATE TABLE books
(
id serial primary key,
isbn text,
author text,
title text,
edition text,
teaser text
);
SELECT row_to_json(row)
FROM
(
SELECT id AS bookid,
author,
cover
FROM books
INNER JOIN
(
SELECT id, title, edition, teaser
FROM books
) cover(id, title, edition, teaser)
USING (id)
) row;
结果:
{
"bookid": 1,
"author": "Bjarne Stroustrup",
"cover": {
"id": 1,
"title": "Design and Evolution of C++",
"edition": "1st edition",
"teaser": "This book focuses on the principles, processes and decisions made during the development of the C++ programming language"
}
}
我想删除 "cover" 中的 "id"。
你需要id才能加入,所以没有id你不能做这么短的查询。你需要构造它。像:
select row_to_json(row,true)
FROM
(
with a as (select id,isbn,author,row_to_json((title,edition,teaser)) r from books
)
select a.id AS bookid,a.author, concat('{"title":',r->'f1',',"edition":',r->'f2',',"teaser":',r->'f3','}')::json as cover
from a
) row;
row_to_json
--------------------------------------------------------
{"bookid":1, +
"author":"\"b\"", +
"cover":{"title":"c","edition":"d","teaser":"\"b\""}}
(1 row)
同样,如果没有加入,您使用的资源会减少两倍
事实证明这是一项棘手的任务。据我所知,用一个简单的查询是不可能实现的。 一种解决方案是使用预定义的数据类型:
CREATE TYPE bookcovertype AS (title text, edition text, teaser text);
SELECT row_to_json(row)
FROM
(
SELECT books.id AS bookid, books.author,
row_to_json(row(books.title, books.edition, books.teaser)::bookcovertype) as cover
FROM books
) row;
为了完整起见,我自己偶然发现了另一个答案:可以通过字符串函数消除附加字段。但是,我更喜欢 AlexM 的回答,因为它会更快并且仍然与 PostgreSQL 9.2 兼容。
SELECT regexp_replace(
(
SELECT row_to_json(row)
FROM
(
SELECT id AS bookid,
author,
cover
FROM books
INNER JOIN
(
SELECT id, title, edition, teaser
FROM books
) cover(id, title, edition, teaser)
USING (id)
) row
)::text,
'"id":\d+,',
'')