我尝试在PostgreSQL中选择此分层JSON作为表
JSON脚本:
'{"NODES":[{"DESC_D":"fam","SEQ":"1","ID":"2304500","NODES":[{"DESC_D":"test 1","SEQ":"2.1","ID":"5214","NODES":[{"DESC_D":"test 1.1","SEQ":"3.1","ID":"999"}]},{"DESC_D":"test 2","SEQ":"2.2","ID":"74542"}]}]}'
The output I'm trying to get (click this link)
这是一个朋友写的解决方案。它做了所需的,但以一种复杂的方式,有没有更简单的解决方案?
WITH RECURSIVE CTE(SEQ, DESC_D, ID, PARENT_ID, NODES) AS (
SELECT json_extract_path_text(e.element, 'SEQ') SEQ,
json_extract_path_text(e.element, 'DESC_D') DESC_D,
json_extract_path_text(e.element, 'ID') ID,
NULL PARENT_ID,
json_extract_path(e.element, 'NODES') NODES
FROM json_each('{"NODES":[{"DESC_D":"fam","SEQ":"1","ID":"2304500","NODES":[{"DESC_D":"test 1","SEQ":"2.1","ID":"5214","NODES":[{"DESC_D":"test 1.1","SEQ":"3.1","ID":"999"}]},{"DESC_D":"test 2","SEQ":"2.2","ID":"74542"}]}]}'::JSON) a(KEY, val)
CROSS JOIN LATERAL json_array_elements(a.val) e(element)
WHERE json_typeof(a.val) = 'array'
UNION ALL
SELECT json_extract_path_text(e.element, 'SEQ') SEQ,
json_extract_path_text(e.element, 'DESC_D') DESC_D,
json_extract_path_text(e.element, 'ID') ID,
r.ID PARENT_ID,
json_extract_path(e.element, 'NODES') NODES
FROM CTE r
CROSS JOIN LATERAL json_array_elements(r.NODES) e(element)
)
SELECT DISTINCT ON (ID) *
FROM CTE;
2条答案
按热度按时间wnrlj8wa1#
可以使用jsonpath类型、函数和语言:
结果:
| 顺序|描述_d|身份证|父代标识|节点|
| - ------| - ------| - ------| - ------| - ------|
| 1个|法姆|二三零四五零零|零|[{"识别号":" 5214 ","序列号":"2.1"、"节点":[{"识别号":" 999 ","序列号":"3.1"、"描述_D":"测试1.1 "}],"描述_D ":"测试1 "},{" ID":"74542","序列号":"2.2"、"描述_D":"测试2 "}]|
| 2.1 |测试1|小行星5214|二三零四五零零|[{"识别号":" 999 ","序列号":"3.1"、"描述_D":"测试1.1 "}]|
| 2.2 |测试2|小行星7454|二三零四五零零|零|
| 3.1 |测试1.1|九九九|小行星5214|零|
参见dbfiddle
nmpmafwu2#
你朋友的答案是正确的(Edouard的方法也是如此)。有两件事可能会使递归查询更容易阅读。您可以使用
->>
操作符,它基本上执行json_extract_path_text函数。您也可以省略CROSS JOIN LATERAL
,因为任何返回集合的函数在FROM
后面加上逗号时都暗示了连接类型。在您的情况下,ID是唯一的,因此不需要DISTINCT ON (ID)
,但如果JSON * 可能 * 有重复的ID,则需要将其放回。为了让它更容易理解,只要记住关于
UNION ALL
的部分永远是你的出发点,后面的部分是深入挖掘,只要分别看每个部分就可以帮助你理解它。