在嵌套的JSON数组

时间:2017-12-19 23:02:13

标签: sql json postgresql greatest-n-per-group

Postgres 10:我在下面有一张表和一个查询:

CREATE TABLE individuals (
    uid character varying(10) PRIMARY KEY,
    data jsonb
);

SELECT data->'files'  FROM individuals WHERE uid = 'PDR7073706'

它返回这个结构:

[
{"date":"2017-12-19T22-35-49","type":"indiv","name":"PDR7073706_indiv_2017-12-19T22-35-49.jpeg"},
{"date":"2017-12-19T22-35-49","type":"address","name":"PDR7073706_address_2017-12-19T22-35-49.pdf"}
]

我正在努力按日期和时间添加两个过滤器。喜欢(非法的伪代码!):

WHERE'type'=“indiv”

或者喜欢:

WHERE'type'=“indiv”AND max('date')

这可能很容易,但我无法破解这个坚果,需要你的帮助!

1 个答案:

答案 0 :(得分:1)

假设缺少信息,数据类型 jsonb 使用包含运算符@>作为第一个子句( WHERE'type'=“indiv”):

SELECT data->'files'
FROM   individuals
WHERE  uid = 'PDR7073706'
AND    data -> 'files' @> '[{"type":"indiv"}]';

可以支持各种索引。参见:

第二个子句( AND max('date'))更棘手。假设你的意思是:
获取带有"type":"indiv"的JSON数组元素也包含最新"date"的行。

SELECT i.*
FROM   individuals i
JOIN   LATERAL (
   SELECT *
   FROM   jsonb_array_elements(data->'files')
   ORDER  BY to_timestamp(value ->> 'date', 'YYYY-MM-DD"T"HH24-MI-SS') DESC NULLS LAST
   LIMIT  1
   ) sub ON sub.value -> 'type' = '"indiv"'::jsonb
WHERE  uid = 'PDR7073706'
AND    data -> 'files' @> '[{"type":"indiv"}]' -- optional; may help performance

to_timestamp(value ->> 'date', 'YYYY-MM-DD"T"HH24-MI-SS')是您对未申报时间戳格式的有根据的猜测。 Details in the manual here.

最后一个过滤器是冗余和可选的。但它可能有助于性能(很多)如果它是有选择性的(只有几行符合条件)并且你有一个匹配的索引建议:

AND    data -> 'files' @> '[{"type":"indiv"}]'

相关: