Teradata 如何使用递归构建 JSON 层次结构

Teradata how to use recursion to build JSON hierarchy

什么是等效的 Teradata 语法来回答关于在 处找到的常见 table 表达式内部反向聚合的相同问题?

我正在尝试破解 Teradata 语法版本以迭代父子关系 table 并构建 JSON 将子的父项放置在父子关系中一个 JSON 字段。

这是上面列出的超链接问题中给出的答案,我认为它是为 PostgreSQL 编写的。我非常感谢帮助将其翻译成 TD,因为我认为这个答案应该能让我完成我的预期任务。如果不是,请让我直截了当。

我不确定 row_to_json(c) 调用的是什么 JSON_AGG(c.children)?我认为双冒号 (NULL::JSON) 正在将 null 转换为 JSON 数据类型?无论如何,我尝试了一些变体都无济于事。请帮忙。

这是给出的 PostgreSQL 语法答案:

WITH RECURSIVE cte AS (
   SELECT id, parent_id, name, NULL::JSON AS children
   FROM   people p
   WHERE  NOT EXISTS (  -- only leaf nodes; see link below
      SELECT 1 FROM people
      WHERE  parent_id = p.id
      )
   UNION ALL
   SELECT p.id, p.parent_id, p.name, row_to_json(c) AS children
   FROM   cte c
   JOIN   people p ON p.id = c.parent_id
   )
SELECT id, name, json_agg(children) AS children
FROM   cte
GROUP  BY 1, 2;

在将 PostgreSQL 转换为 Teradata 时,我遇到了一个限制,JSON 列不受 UNION 等集合操作的支持。

来回转换 JSON/VarChar 是一种解决方法:

CREATE VOLATILE TABLE people (id INT, name VARCHAR(20), parent_id INT) ON COMMIT PRESERVE ROWS;

INSERT INTO people VALUES(1, 'Adam', NULL);
INSERT INTO people VALUES(2, 'Abel',  1);
INSERT INTO people VALUES(3, 'Cain',  1);
INSERT INTO people VALUES(4, 'Enoch', 3);

WITH RECURSIVE cte AS (
   SELECT id, parent_id, name,
      CAST(NULL AS VARCHAR(2000)) AS children
   FROM   people p
   WHERE  NOT EXISTS (
      SELECT * FROM people
      WHERE  parent_id = p.id
      )
   UNION ALL
   SELECT p.id, p.parent_id, p.name,
      -- VarChar -> JSON -> VarChar
      CAST(JSON_COMPOSE(c.id, 
                        c.name,
                        NEW JSON(c.children) AS children) AS VARCHAR(10000)) AS children
   FROM   cte c                                       
   JOIN   people p ON p.id = c.parent_id
   )
SELECT id, name,
   JSON_AGG(NEW JSON(children) AS children) AS children
FROM cte
GROUP  BY 1, 2;

结果类似,但不完全相同,Teradata 添加"children":,例如:

{"children":{"id":4,"name":"Enoch","children":null}} -- Teradata
           [{"id":4,"name":"Enoch","children":null}] -- PostgreSQL

最后添加 JSONExtract 以仅获取数组:

SELECT id, name,
     JSON_AGG(NEW JSON(children) AS X).JSONExtract('$..X') AS children
FROM cte
GROUP  BY 1, 2;

            [{"id":4,"name":"Enoch","children":null}]