【问题标题】:How do I Query an Adjacency relation (in SQL) to get a Leaf by providing a Path?如何通过提供路径查询邻接关系(在 SQL 中)以获取叶子?
【发布时间】:2023-03-21 23:25:02
【问题描述】:

各位程序员朋友您好!

我有这个包含类别和子类别的表(实际上我没有,但让我们坚持一个经典示例):

Id     ParentId     Name
1      NULL         A
2      1            B
3      2            C
4      3            D

5      NULL         B
6      5            D

有没有办法让我通过查询表的完整路径来获得类别“D”(id 4)? (见下面的伪代码)

SELECT * FROM Categories WHERE FullPath = "A/B/C/D"

// Result:
Id     ParentId     Name
4      3            D

我知道可以使用左连接来获取完整路径,但是如何编写查询以通过提供路径来获取叶节点?

编辑(解决方案):

帮助 van 和 Eric 的帮助,这就是我所做的:

with p as
(
    select
        c.*,
        cast(c.Name as varchar(1024)) as NamePath
    from
        Categories c
    where 
        ParentCategoryId is null
    union all
    select
        c.*,
        cast(p.NamePath + '/' + c.Name as varchar(1024)) as NamePath
    from
        Categories c
        inner join p on
            c.ParentCategoryId = p.CategoryId
)
select Id, Name
from p
where NamePath = 'A/B/C/D'

谢谢大家,你们的回答都非常有帮助!我希望我能够将它们都标记为解决方案。

这一次我会选择积分最少的(即van)。

【问题讨论】:

  • 你想要这个做什么? SQL Server 2008 允许您使用 hierarchyid 数据类型完全按照您的意愿行事,但是对于
  • 我在寻找一个通用的 SQL 实现。但是该应用程序将构建在 SQL Server 2k8 之上,并且将使用 LINQ2SQL 或 EF 获取数据。所以我不认为 hierarchyid 数据类型是一个选项,对吧?

标签: sql mysql sql-server linq-to-sql


【解决方案1】:

在 CTE 的帮助下:

WITH CategoriesWithPath (id, parentid, name, path) AS
(
    SELECT  c.*, cast(c.name AS VARCHAR(1024)) AS "path"
    FROM    @Categories c
    WHERE   parentid is null
    UNION ALL
    SELECT  c.*, cast(p."path" + '/' + c.name AS VARCHAR(1024)) AS "path"
    FROM    @Categories c
    INNER JOIN CategoriesWithPath p ON c.parentid = p.id
)
SELECT  id, parentid, name 
FROM    CategoriesWithPath
WHERE   "path" = 'a/b/c/d'

但我会使用这个 CTA 创建一个视图,这样您就可以轻松地从这个基于“路径”过滤器的视图中执行 SELECT

【讨论】:

    【解决方案2】:

    这是使用公用表表达式 (CTE) 的 SQL Server (2005+) 方法:

    declare @leaf varchar(10)
    declare @fullpath varchar(50)
    
    set @leaf = 'D'
    set @fullpath = '/A/B/C/D'
    
    with p as
    (
        select
            *,
            '/' + name as path
        from
            categories 
        where 
            leaf = @leaf
        union all
        select
            c.*,
            '/' + name + p.path as path
        from
            categories c
            inner join p on
                c.id = p.parentid
    )
    
    select
        *
    from
        p
    where
        path = @fullpath
    

    【讨论】:

      【解决方案3】:

      虽然没有直接回答您的问题,但如果您可以访问 SQL Server 2008,您可能需要考虑使用Hierarchid data type

      【讨论】:

      • 是的,我知道新的数据类型...但是要构建的应用程序将使用实体框架作为其数据模型,我相信尚不支持该数据类型。谢谢
      【解决方案4】:

      我没有看到这样做的意义,因为您已经构建了路径并且知道“D”是什么。你不能只用'\'分割路径并使用最后一项进行查询。

      【讨论】:

      • 没有。 “D”只是路径的一部分。仅查询 D 的 db 将给出所有(第一个)带有“D”的元组......而不是完整路径的叶节点。
      猜你喜欢
      • 2020-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多