当前位置: 首页 > 面试题库 >

公用表表达式内的反向聚合

晁砚
2023-03-14
问题内容

我本来希望以下查询返回所有带有各自子代的人。

WITH RECURSIVE nested_people (id, name, children) AS (
   SELECT id, name, NULL::JSON AS children
   FROM people
   WHERE parent_id IS NULL
 UNION ALL
   SELECT people.id, people.name, ROW_TO_JSON(nested_people.*) AS children
   FROM people
   JOIN nested_people ON people.parent_id = nested_people.id
)
SELECT * FROM nested_people;

但是实际上,它的确是相反的。我想不出无需额外的CTE就能进行正确嵌套的方法。有办法吗?

示例数据

+----+-------+-----------+
| id | name  | parent_id |
+----+-------+-----------+
|  1 | Adam  | null      |
|  2 | Abel  | 1         |
|  3 | Cain  | 1         |
|  4 | Enoch | 3         |
+----+-------+-----------+

结果

+----+-------+--------------------------------------------------------------------------+
| id | name  |                                children                                  |
+----+-------+--------------------------------------------------------------------------+
|  1 | Adam  | null                                                                     |
|  2 | Abel  | {"id":1,"name":"Adam","children":null}                                   |
|  3 | Cain  | {"id":1,"name":"Adam","children":null}                                   |
|  4 | Enoch | {"id":3,"name":"Cain","children":{"id":1,"name":"Adam","children":null}} |
+----+-------+--------------------------------------------------------------------------+

预期结果

+----+-------+----------------------------------------------------------------------------------------------------------------------+
| id | name  |                                                       children                                                       |
+----+-------+----------------------------------------------------------------------------------------------------------------------+
|  1 | Adam  | [{"id":2, "name":"Abel", "children":null},{"id":3,"name":"Cain","children":[{"id":4,"name":"Enoch","children":null}] |
|  2 | Abel  | null                                                                                                                 |
|  3 | Cain  | [{"id":4,"name":"Enoch","children":null}]                                                                            |
|  4 | Enoch | null                                                                                                                 |
+----+-------+----------------------------------------------------------------------------------------------------------------------+

问题答案:

该rCTE从另一侧遍历树:

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;

SQL提琴。

使用json_agg()到每个节点聚集多个分支外SELECT
与您期望的结果之间的微小差异:

  • 这包括parent_idchildren列中。
  • 没有将单个节点包装到数组中。

都可以进行调整,但是我希望结果对您来说是可以的。



 类似资料:
  • 问题内容: 我必须先匹配一个数字,然后再匹配14次。然后,我来到了regexstor.net/tester中的以下正则表达式: 编辑 当我将其粘贴到代码中时,包括正确的反斜杠: 我已经用来替换了反向引用,该反向引用用于替换Java中的匹配项。 然后我意识到这是行不通的。在Java中,当需要在REGEX中向后引用匹配项时,必须使用,但是要替换它时,运算符为。 我的问题是:为什么? 问题答案: 在Ja

  • 本文向大家介绍Java正则表达式中的反向引用,包括了Java正则表达式中的反向引用的使用技巧和注意事项,需要的朋友参考一下 捕获组是一种将多个字符视为一个单元的方法。通过将要分组的字符放在一组括号内来创建它们。例如,正则表达式(狗)创建一个包含字母“ d”,“ o”和“ g”的单个组。 捕获组通过从左到右计数其开括号来编号。例如,在表达式((A)(B(C)))中,有四个这样的组- 示例 反向引用允

  • 问题内容: 在MSSQL 2008中使用多个CTE时,通常用逗号将它们分开。 但是,当我在Teradata环境中尝试此操作时,语法出现错误。 适用于MS SQL: 现在,尝试使用Teradata语法: 语法错误,应在’,’和’RECURSIVE’关键字之间使用名称或Unicode分隔标识符之类的名称。 第二次尝试(不使用RECURSIVE多次) 不支持多个WITH定义。 问题答案: Teradat

  • 本文向大家介绍postgresql SELECT查询中的公用表表达式,包括了postgresql SELECT查询中的公用表表达式的使用技巧和注意事项,需要的朋友参考一下 示例 公用表表达式支持提取较大查询的部分。例如:            

  • 问题内容: SQLite是否支持公用表表达式? 我想运行这样的查询: 问题答案: 从Sqlite版本3.8.3开始,SQLite支持公用表表达式。 变更记录 指示

  • 我试图用聚合物表达式来显示某些东西。 我有一个文件,它打印出json_encoded数组,例如名称。在我看来,有三种可能性: null