繁体   English   中英

需要从Postgresql表中动态选择JSON数组元素

[英]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

但是,我还需要一个级别-评估最后一项,如果它与名称字段相同,则尝试倒数第二个字段,依此类推。

任何帮助或指针将不胜感激!

Postgres 9.3中的json

在9.3版中很难做到这一点,因为缺少有用的功能。

方法1

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在注释中提供的表达式,改进了从jsontext的转换。 仍然有点破旧,但应该是安全的。

方法2

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 ,得到与上述相同的结果。

SQL提琴。

Postgres 9.4中的jsonjsonb

第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 其他都一样。

手册中的json / jsonb函数

相关答案以及更多说明:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM