![](/img/trans.png)
[英]Select from JSON Array postgresql JSON column
[英]Need to select a JSON array element dynamically from a postgresql table
我的数据如下:
ID Name Data
1 Joe ["Mary","Joe"]
2 Mary ["Sarah","Mary","Mary"]
3 Bill ["Bill","Joe"]
4 James ["James","James","James"]
我想编写一个查询,该查询从数组中选择LAST元素,这不等于Name字段。 例如,我希望查询返回以下结果:
ID Name Last
1 Joe Mary
2 Mary Sarah
3 Bill Joe
4 James (NULL)
我正在接近-我可以使用以下查询选择最后一个元素:
SELECT ID, Name,
(Data::json->(json_array_length(Data::json)-1))::text AS Last
FROM table;
ID Name Last
1 Joe Joe
2 Mary Mary
3 Bill Joe
4 James James
但是,我还需要一个级别-评估最后一项,如果它与名称字段相同,则尝试倒数第二个字段,依此类推。
任何帮助或指针将不胜感激!
json
在9.3版中很难做到这一点,因为缺少有用的功能。
在LEFT JOIN LATERAL
(干净且符合标准)中嵌套,将json
双引号修剪为强制转换为text
。 请参阅下面的链接。
SELECT DISTINCT ON (1)
t.id, t.name, d.last
FROM tbl t
LEFT JOIN LATERAL (
SELECT ('[' || d::text || ']')::json->>0 AS last
FROM json_array_elements(t.data) d
) d ON d.last <> t.name
ORDER BY 1, row_number() OVER () DESC;
尽管这可行,但我从未见过失败,但未嵌套元素的顺序取决于未记录的行为。 请参阅下面的链接!
使用@pozs在注释中提供的表达式,改进了从json
到text
的转换。 仍然有点破旧,但应该是安全的。
SELECT DISTINCT ON (1)
id, name, NULLIF(last, name) AS last
FROM (
SELECT t.id, t.name
,('[' || json_array_elements(t.data)::text || ']')::json->>0 AS last
, row_number() OVER () AS rn
FROM tbl t
) sub
ORDER BY 1, (last = name), rn DESC;
SELECT
列表中(非标准)。 rn
)(更可靠)。 text
。 ORDER BY
子句中的表达式(last = name)
对匹配的名称进行最后排序(但在NULL之前)。 因此,仅当没有其他名称可用时,才选择匹配的名称。 下面的最后一个链接。 在SELECT
列表中, NULLIF
将匹配的名称替换为NULL
,得到与上述相同的结果。 json
或jsonb
第9.4页提供了所有必要的改进:
SELECT DISTINCT ON (1)
t.id, t.name, d.last
FROM tbl t
LEFT JOIN LATERAL json_array_elements_text(data) WITH ORDINALITY d(last, rn)
ON d.last <> t.name
ORDER BY d.rn DESC;
将jsonb_array_elements_text()
用于jsonb
。 其他都一样。
相关答案以及更多说明:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.