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

SQL-将非空邻接列表转换为路径

华宇
2023-03-14
问题内容

我正在处理代表文件系统的一些表,我需要选择每个文件夹的完整路径作为扁平字符串。

第一个表列出了每个文件夹的详细信息:

CREATE TABLE Folders(
    FolderID int IDENTITY(1,1) NOT NULL,
    [Name] nvarchar(255) NOT NULL)

第二张表列出了文件夹关系的传递性关闭:

CREATE TABLE FolderClosures(
    FolderClosuresID int IDENTITY(1,1) NOT NULL,
    AncestorFolderID int NOT NULL, --Foreign key to Folders.FolderID
    DescendantFolderID int NOT NULL --Foreign key to Folders.FolderID
    IsDirect bit NOT NULL)

对于示例数据,我们假设存在以下文件夹:

Documents/
Documents/Finance/
Documents/HumanResources/
Documents/HumanResources/Training/

这些将在以下表格中保留:

| FolderID | Name           |
+----------+----------------+
|        1 | Documents      |
|        2 | Finance        |
|        3 | HumanResources |
|        4 | Training       |

| FolderClosureID | AncestorFolderID | DescendantFolderID | IsDirect |
+-----------------+------------------+--------------------+----------+
|               1 |                1 |                  1 |        0 |
|               2 |                2 |                  2 |        0 |
|               3 |                1 |                  2 |        1 |
|               4 |                3 |                  3 |        0 |
|               5 |                1 |                  3 |        1 |
|               6 |                4 |                  4 |        0 |
|               7 |                1 |                  4 |        0 |
|               8 |                3 |                  4 |        1 |

需要注意的一些细节:

  1. 每个文件夹中都有一个“身份排” FolderClosures,在那里AncestorFolderID = DescendantFolderID AND IsDirect = 0

  2. 每个不是顶级文件夹的文件夹在FolderClosures其中仅包含一行IsDirect = 1

  3. FolderClosures每个文件夹可以包含许多行,其中AncestorFolderID <> DescendantFolderID AND IsDirect = 0。这些中的每一个都代表“祖父母”或更远的关系。

  4. 由于没有列可为空,因此没有行明确指出给定文件夹是顶级文件夹。这只能通过检查,有中没有行可以看出端倪FolderClosures,其中IsDirect = 1 AND DescendantFolderID = SomeID地方SomeID是有问题的文件夹的ID。

我希望能够运行返回此数据的查询:

| FolderID | Path                               |
+----------+------------------------------------+
|        1 | Documents/                         |
|        2 | Documents/Finance/                 |
|        3 | Documents/HumanResources/          |
|        4 | Documents/HumanResources/Training/ |

文件夹可以无限深度嵌套,但实际上最多只能嵌套10个级别。查询可能需要返回数千个文件夹的路径。

当数据作为邻接表持久存储时,我已经找到了很多有关创建此类查询的建议,但是我无法找到这样的传递闭包设置的答案。我发现的邻接表解决方案依赖于具有可空父文件夹ID的行,但这在这里行不通。

如何获得所需的输出?

如果有帮助,我正在使用SQL Server 2016。


问题答案:

获得所需输出的一种方法是进行递归查询。为此,我认为最好的方法是仅使用具有的行,IsDirect = 1并使用锚作为所有没有直接父级的文件夹FolderClosures,这应该是您的所有根文件夹。

WITH FoldersCTE AS (
    SELECT  F.FolderID, CAST(F.Name as NVARCHAR(max)) Path
    FROM    Folders F
    WHERE   NOT EXISTS (
        SELECT 1 FROM FolderClosures FC WHERE FC.IsDirect = 1 AND FC.DescendantFolderID = F.FolderID
    )
    UNION ALL
    SELECT  F.FolderID, CONCAT(PF.Path, '\', F.Name)
    FROM    FoldersCTE PF
            INNER JOIN FolderClosures FC
                ON  FC.AncestorFolderID = PF.FolderId
                AND FC.IsDirect = 1
            INNER JOIN Folders F
                ON F.FolderID = FC.DescendantFolderID
)
SELECT * 
FROM    FoldersCTE  
OPTION (MAXRECURSION 1000) --> how many nested levels you think you will have

这将产生:

FolderID    Path
1           Documents
2           Documents\Finance
3           Documents\HumanResources
4           Documents\HumanResources\Training

希望能帮助到你。



 类似资料:
  • 问题内容: 鉴于我在Swift中有一个数组,例如,有一种方法会将其转换为元组数组:。 以下是一些有关行为方式的示例: 应该返回,因为它没有对。 也应该返回,因为它没有对。 应该是。它只有一对。 我可以为此编写代码,但我想作为的扩展使用,以便它返回成对的a。这将使得它可用在任何序列,并与方法,如兼容,,,等。 我该如何创建这样的一个?以及如何编写以这种方式进行转换的方法,以便可以尽可能灵活地使用它?

  • 问题内容: 我是python的初学者。我想将sql结果转换为列表。这是我的代码: 我的表中有6列,但是此代码不会创建6元素列表。我在哪里做错了? 问题答案: 如果你有一个迭代在Python,做一个列表,可以简单地调用了内置: 请注意,可迭代项通常与列表一样有用,并且可能会变得更懒惰,因此效率更高。 您的原始代码失败了,因为它没有太多意义。您遍历行并枚举它们,这样就得到等等…-这意味着您正在建立第n

  • 问题内容: 考虑下面的示例,其中有一个包含人员记录的 Person 表和一个包含链接到人员的可选属性的 PersonAttribute 表: Table: Person Table PersonAttribute 我将如何编写一个查询,使所有具有属性的人都像列一样返回?我需要的结果集是: 因此,从本质上讲,我需要编写一个查询,该查询将获取所有带有所有唯一属性键的人记录,这些键被转换为具有每个人记录

  • 问题内容: 我的表包含以下列: 我想显示如下: 如您所见,我想将列与自定义列名成对显示。这对是列A和B,列C和D以及列C和D。 问题答案:

  • 问题内容: 我在Postgres中有一个包含此数据的表,并且很难将其转换为JSON对象。 我该如何转换呢? 任何建议都会有所帮助。谢谢 问题答案: 使用(https://www.postgresql.org/docs/current/static/queries- with.html )和JSON函数(https://www.postgresql.org/docs/current/static/f