【问题标题】:How to get a hierarchy table in Sql Server如何在 Sql Server 中获取层次结构表
【发布时间】:2019-09-03 09:01:03
【问题描述】:

我想创建一个显示另一个 SQL Server 表的层次结构的表。 我有一个具有以下结构的表

+-----------+----------+
| AccountID | ParentID |
+-----------+----------+
| 1         |          |
+-----------+----------+
| 2         | 1        |
+-----------+----------+
| 3         | 1        |
+-----------+----------+
| 4         | 2        |
+-----------+----------+
| 5         | 3        |
+-----------+----------+
| 6         | 5        |
+-----------+----------+

并希望获得另一个具有以下结构的表

+-----------+------+
| AccountID | Path |
+-----------+------+
| 1         | 1    |
+-----------+------+
| 2         | 1    |
+-----------+------+
| 2         | 2    |
+-----------+------+
| 3         | 1    |
+-----------+------+
| 3         | 3    |
+-----------+------+
| 4         | 1    |
+-----------+------+
| 4         | 2    |
+-----------+------+
| 4         | 4    |
+-----------+------+
| 5         | 1    |
+-----------+------+
| 5         | 3    |
+-----------+------+
| 5         | 5    |
+-----------+------+
| 6         | 1    |
+-----------+------+
| 6         | 3    |
+-----------+------+
| 6         | 5    |
+-----------+------+
| 6         | 6    |
+-----------+------+

注意:在父母 ID 字段中,您必须始终包含您自己的 ID,即 1-1、2-2 等。

如果您在第一个表中看到,对于 AccountID 1,没有 ParentID,因为它是最高层级。但是在我需要提取的表中,您会看到 AccountID 1 的值 1 出现在 Path 列中。其余的值也是如此,也就是说,对于 AccountID 2,在结果表中 AccountID 1 出现(它的上级层次值),但它也必须包含值 2。所以对于其余的AccountID 列中的值。

设置示例数据:

create table Account 
(
  AccountID INT,
  ParentID INT NULL
 )

 INSERT INTO Account(AccountID, ParentID)
 VALUES
 (1, NULL),
 (2,1),
 (3,1),
 (4,2),
 (5,3),
 (6,5)   

我无法得到这个结果。你能帮帮我吗?

提前致谢

【问题讨论】:

  • 到目前为止你尝试过什么?你看过 rCTE 吗? SO上有很多这样的东西;为什么这些例子对你没有帮助?
  • 只是为了澄清@Larnu 的评论,rCTE 是一个递归公用表表达式。它可能会帮助您缩小搜索范围;)但是,CTE 在处理分层数据时非常有效。
  • 我查看了几篇使用递归 CTE 的帖子,但我不知道如何使用它。
  • 我不确定您所说的“在父母 ID 字段中,您必须始终包含您自己的 ID,即 1-1、2-2”,因为这与您的示例不匹配,请解释路径应该如何派生。
  • @SteveFord,例如,结果表必须包含 AccountID 1、ParentID 1 字段。对于 AccountID 2,它必须同时包含 ParentID 1 和 ParentID 2。也就是说,除了对应的 ParentID 之外,它还必须始终包含具有自己 ID 的行。

标签: sql sql-server hierarchy


【解决方案1】:

如前所述,实现此目的的最简单方法是使用 rCTE,然后递归向下层次结构的每一层,直到到达底部:

--Sample Data
WITH YourTable AS(
    SELECT V.AccountID,
           V.[Path]
    FROM (VALUES(1,NULL),
                (2,1),
                (3,1),
                (4,2),
                (5,3),
                (6,5))V(AccountID,[Path])),
--Solution
rCTe AS(
    SELECT YT.AccountID AS RootID,
           YT.AccountID,
           YT.[Path]
    FROM YourTable YT
    UNION ALL
    SELECT r.RootID,
           YT.AccountID,
           YT.[Path]
    FROM rCTe r
         JOIN YourTable YT ON r.[Path] = YT.AccountID)
SELECT r.RootID AS AccountID,
       r.AccountID AS [Path]
FROM rCTe r
ORDER BY AccountId,
         [Path];

DB<>Fiddle

【讨论】:

  • 你忘记了With前的分号。
  • @MarkKram 嗯?为什么;WITH 之前会有一个;; 是语句终止符,WITH 之前没有语句。即便如此,; 不会 WITH 之前,它会 之前的语句之后。上面唯一应该有;的地方是有一个的地方;语句结束后 (ORDER BY AccountId, [Path];)。
  • 按照习惯,我总是在 CTE 中的 With 之前添加一个分号,因为 CTE 之前总是有语句。
  • @MarkKram 显然不在上面,但这预示着你有 2 个问题:你为什么要在 WITH 的开头加上 ;; 是一个声明 终止符 不是“初学者”,你为什么不首先正确地终止你的其他陈述?不是DECLARE @I int = 10 {NewLine} ;WITH CTE AS...,而是DECLARE @I int = 10; {NewLine} WITH CTE AS...。不推荐使用的功能是不终止您的语句用分号,而不是“不开始”它们用分号。 (您不会以 ; 开始您的 C# 语句,这会导致您出错。)
  • @Larnu。太感谢了!。你的句子加分号效果很好!。
【解决方案2】:

我根据你的句子尝试了这句话,

WITH rCTe AS (
    SELECT YT.Accountid AS RootID,
           YT.Accountid,
           YT.Parentaccountid
    FROM PBI_OrganizacionJerarquica YT
    UNION ALL
    SELECT r.RootID,
           YT.Accountid,
           YT.Parentaccountid
    FROM rCTe r
         JOIN PBI_OrganizacionJerarquica YT ON r.Parentaccountid = YT.Accountid)

SELECT r.RootID AS AccountID,
       r.Accountid AS [Path]
FROM rCTe r
ORDER BY AccountId,
         [Path];

我得到了这个错误

消息 319,第 15 级,状态 1,第 3 行 关键字“with”附近的语法不正确。如果这个语句是一个公用表表达式、一个 xmlnamespaces 子句或一个更改跟踪上下文子句,则前面的语句必须以分号结束。

【讨论】:

  • 请避免将建议答案作为新答案出现问题。这会使将来可能偶然发现您的问题的其他人感到困惑。建议在您回复的答案下方留下评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 2016-07-25
  • 2015-07-28
  • 1970-01-01
相关资源
最近更新 更多