【问题标题】:Hierarchical query - show parent name when all children present分层查询 - 当所有孩子都在场时显示父母姓名
【发布时间】:2021-06-18 12:25:08
【问题描述】:

问题

我正在努力解决 Postgres 的分层问题。

我有多层层次结构(我们假设 3 出于问题的目的)

-> category
--> subcategory
---> item

这些是不同的表,但我可以简单地将其转换为一个子父表/CTE。每个父类别可以有多个子类别。

我还有另一个表,比如说 UserPreferences,其中用户和项目之间存在关系(用户选择哪些项目作为首选项)。

我需要做的是创建一个查询,该查询将返回所有用户偏好但有一个要求,如果选择了父级下的所有节点,则应显示父级名称而不是子级列表。


示例

如果我们有以下情况:

-> category 1
--> subcategory 1
---> item 1 (selected by user)
---> item 2 (selected by user)
--> subcategory 2
---> item 3 (selected by user)
---> item 4
-> category 2
--> subcategory 3
---> item 5 (selected by user)

那么用户想要的输出是: 子类别 1,项目 3,类别 2

请注意,查询应该允许同时查询多个用户,因此函数不是一个选项。


尝试

我曾多次尝试使用以下方法编写此类查询:

  • 递归 CTE - 我在编写正确条件时遇到了问题:/ 我也有点担心性能 - 如果它足够好的话
  • 按 ROLLUP 分组 + 一些左侧连接以获取类别内的计数 - 但在这里我遇到了“类别 2”的情况 - 因此在我的情况下,将显示“类别 2”和“子类别 2”仅属于“第 2 类”

有没有人有什么建议最好的方法是什么?

【问题讨论】:

    标签: postgresql


    【解决方案1】:

    您应该有一个数据库设计,用间隔而不是嵌套集来表示这个层次结构。然后查询将很简单... 我为此写了一些论文: https://sqlpro.developpez.com/cours/arborescence/#LII 但它是法语... 检查所有子项时查找上层的查询是:

    SELECT *
    FROM   INTERVAL_TREE AS IT
    WHERE  (RIGHT_BOUND - LEFT_BOUND) / 2 =
           (SELECT COUNT(*)
            FROM   INTERVAL_TREE
            WHERE  CHECKED = 1
              AND  RIGHT_BOUND > IT.RIGHT_BOUND
              AND  LEFT_BOUND < IT.LEFT_BOUND) 
    

    当然,谓词“CHECKED = 1”可以是子查询...

    【讨论】:

    • 有趣的方法,虽然我担心在我们的案例中现在实施这个成本太高,所以我们需要接受我们目前拥有的东西。 :(
    • 作为最后的手段,如果我们无法找到灵活的解决方案,我们可以编写此查询,假设我们在层次结构中有恒定数量的级别(在本例中为 4)并且这不会改变。在我们的案例中,最重要的事实是性能
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    • 2014-07-06
    相关资源
    最近更新 更多