【问题标题】:Find level of categories in a hierarchy在层次结构中查找类别级别
【发布时间】:2020-05-29 00:48:00
【问题描述】:

我有一个脚本来查找类别列表的层次结构。但是,我需要知道关卡的深度才能找到所有相应的类别。所以我的问题是有没有更好的方法来重写代码,以便它可以深入到最低级别,而无需我指定深度。如下面的示例,我必须知道类别级别达到 5 级深度才能找到所有类别。

WITH rCTE AS
(
    SELECT
        *,
        0 AS Level
    FROM dbo.inv_category ic
    WHERE ic.Primary_org_id = 56392

    UNION ALL

    SELECT
        t.*,
        r.Level + 1 AS Level
    FROM dbo.inv_category t
    INNER JOIN rCTE r ON t.Parent_id = r.Category_id
)
SELECT DISTINCT
    c1.Parent_id, c1.Category_id, c1.Category,
    c2.Category, c2.Category_id, c2.Parent_id,
    c3.Category, c3.Category_id, c3.Parent_id,
    c4.Category, c4.Category_id, c4.Parent_id,
    c5.Category, c5.Category_id, c5.Parent_id
FROM 
    rCTE c1
LEFT OUTER JOIN 
    rCTE c2 ON c1.Category_id = c2.Parent_id
LEFT OUTER JOIN 
    rCTE c3 ON c2.Category_id = c3.Parent_id
LEFT OUTER JOIN 
    rCTE c4 ON c3.Category_id = c4.Parent_id
LEFT OUTER JOIN 
    rCTE c5 ON c4.Category_id = c5.Parent_id
WHERE 
    c1.Parent_id = 0
ORDER BY 
    c1.Category, c2.Category

【问题讨论】:

  • 如果您想要动态的列数,那么您需要使用“动态 SQL”,首先计算列数(级别),然后动态地组装一条包含所有必要列的 SQL 语句。或者,您可以将所有级别“连接”到一个 VARCHAR 列中,但这可能不是您想要的。

标签: sql sql-server tsql join recursive-query


【解决方案1】:

您的问题是您希望将父类别放在不同的列中,这使任务变得更加复杂。

缩短查询并避免多次连接的一个选项使用条件聚合:

with rcte as (...)
select
    max(case when level = 0 then parent_id   end) parent_id_0,
    max(case when level = 0 then category_id end) category_id_0,
    max(case when level = 0 then category    end) category_0,
    max(case when level = 1 then parent_id   end) parent_id_1,
    max(case when level = 1 then category_id end) category_id_1,
    max(case when level = 1 then category    end) category_1,   
    ...
from rcte

您可以添加更多三元组条件表达式来管理所需的最大级别;当产品的实际层次结构耗尽时,以下列将为空。

另一个选项是字符串聚合。这会为每个原始列生成一个唯一列,所有值按照它们在层次结构中出现的顺序连接:

with rcte as (...)
select
    string_agg(parent_id,      ' > ') within group(order by level) parent_ids,
    string_agg(category_id_id, ' > ') within group(order by level) category_ids,
    string_agg(category,       ' > ') within group(order by level) categories
from rcte

【讨论】:

  • 感谢您的回复!但不是我要找的,因为我需要它来吐出主要类别的名称,然后是所有子类别的名称
  • @Jay:第一个查询就是这样做的,这比您的解决方案开销更少(没有多个连接)。您可以将select 子句扩展为更多列(例如,最多level 10)。
  • 否则如果要根据层次深度动态创建列,则需要动态SQL。这要复杂得多(问题中最初没有提到)。
猜你喜欢
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 2013-07-04
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多