如何连接 jsonb 列中的嵌套值?

问题描述 投票:0回答:2

我有一个包含这些表的 PostgreSQL 11 数据库:

CREATE TABLE stats (
   id integer NOT NULL,
   uid integer NOT NULL,
   date date NOT NULL,
   data jsonb DEFAULT '[]'::json NOT NULL
);
INSERT INTO stats(id, uid, date, data) VALUES
   (1, 1, '2020-10-01', '{"somerandomhash":{"source":"thesource"}}');

CREATE TABLE links(
   id integer NOT NULL,
   uuid uuid NOT NULL,
   path text NOT NULL
);
INSERT INTO links(id, uuid, path) VALUES
   (1, 'acbd18db-4cc2-f85c-edef-654fccc4a4d8', 'thesource');

我的目标是使用

reports
表中的
data
创建一个新表
stats
,但使用
links
表中的新密钥。它看起来像这样:

CREATE TABLE reports(
    id integer NOT NULL,
    uid integer NOT NULL,
    date date NOT NULL,
    data jsonb DEFAULT '[]'::json NOT NULL
);

INSERT INTO reports(id, uid, date, data) VALUES
   (1, 1, 2020-10-01, {"uuid":{"source":"thesource"});

为此,我尝试左连接表

links
以检索
uuid
列值 - 但没有运气:

SELECT s.uid, s.date, s.data->jsonb_object_keys(data)->>'source' as path, s.data->jsonb_object_keys(data) as data, l.uuid
FROM stats s LEFT JOIN links l ON s.data->jsonb_object_keys(data)->>'source' = l.path

我尝试在左连接中使用 s.data->jsonb_object_keys(data)->>'source' 的结果,但收到错误:

ERROR:  set-returning functions are not allowed in JOIN conditions

我尝试使用

LATERAL
但仍然没有有效的结果。
如何做到这一点?

sql postgresql left-join jsonb set-returning-functions
2个回答
2
投票

jsonb_object_keys()
是一个设置返回函数,不能按照您的方式使用 - 正如错误消息告诉您的那样。更重要的是,
json_object_keys()
返回顶级 key(s),但似乎您只对 value 感兴趣。尝试改为
jsonb_each()

SELECT s.id
     , s.uid
     , s.date
     , jsonb_build_object(l.uuid::text, o.value) AS new_data
FROM   stats s
CROSS  JOIN LATERAL jsonb_each(s.data) o  -- defaults to column names (key, value)
LEFT   JOIN links l ON l.path = o.value->>'source';

小提琴

jsonb_each()
返回顶级键 值。仅使用继续。

嵌套的 JSON 对象似乎具有常量键名称 'source'。所以连接条件是

l.path = o.value->>'source'

最后,使用

jsonb
 构建新的 
jsonb_build_object()
值。

虽然这可以如所演示的那样工作,但仍然存在一些问题:

  • 上面假设 stats.data 中始终存在

    one
    顶级密钥。如果没有,您必须定义要做什么...

  • 上面假设表

    links
    中始终只有一个匹配项。如果没有,您必须定义要做什么...

  • 最重要的是,如果

    data
    与您想象的一样有规律,请考虑一个普通的
    uuid
    列(或者无论如何将其删除,因为值在表
    links
    中)和一个普通列
    source 
    替换
    jsonb
    列。 更简单、更高效。


0
投票
您似乎想通过 JSON 列中的“source”键加入。

而不是

s.data->jsonb_object_keys(data)->>'source'

试试这个

s.data ->> 'source'

如果我的假设正确,整个查询可以这样进行:

SELECT s.uid, s.date, s.data ->> 'source' AS path, s.data -> jsonb_object_keys(data) AS data, l.uuid FROM stats s LEFT JOIN links l ON s.data ->> 'source' = l.path
    
© www.soinside.com 2019 - 2024. All rights reserved.