Sql server CTE查询:如何按顺序排列

Sql server CTE查询:如何按顺序排列,sql-server,common-table-expression,Sql Server,Common Table Expression,我有一个表,它以常规的层次结构方式存储公司信息及其母公司,其中包含companyid、parentid和name 我只是学习了Sql Server中的CTE查询并编写了这个查询 WITH tableR (ParentCompanyID, CompanyID, Levels) AS ( -- Anchor member definition SELECT e.ParentCompanyID, e.CompanyID, 0 As Levels FROM tblCompany AS e

我有一个表,它以常规的层次结构方式存储公司信息及其母公司,其中包含companyid、parentid和name

我只是学习了Sql Server中的CTE查询并编写了这个查询

WITH tableR (ParentCompanyID, CompanyID, Levels)
AS
(
-- Anchor member definition
    SELECT e.ParentCompanyID, e.CompanyID, 0 As Levels
    FROM tblCompany AS e   
    WHERE ParentCompanyID in (9)
    UNION ALL
-- Recursive member definition
    SELECT e.ParentCompanyID, e.CompanyID, Levels  + 1
    FROM tblCompany AS e   
    INNER JOIN tableR AS d
        ON e.ParentCompanyID = d.CompanyID
)
-- Statement that executes the CTE
SELECT tabler.Levels, tableR.CompanyID, (left('--------------', (tabler.Levels* 2)) + c.CompanyName) as CName,c.ParentCompanyID
FROM tableR  Left join tblcompany c on tableR.CompanyId=c.CompanyID
这很好,只是它首先列出ID=9的子级,然后列出第一级子级,然后列出第二级。。以此类推,但我需要的是让子数据正好位于其父数据之下,所以

L0
  L1
    L2
  L1-1
    L2-1
 ....
有可能吗?因为如果不是这样,我就必须用我正在使用的C代码递归地执行它

我也试试这个

WITH tableR (ParentCompanyID, CompanyID, Levels, RowNumber)
AS
(
-- Anchor member definition
    SELECT e.ParentCompanyID, e.CompanyID, 1 As Levels, CAST((Row_Number() Over (Order by e.CompanyName) ) as Varchar(MAx)) as RowNumber
    FROM tblCompany AS e   
    WHERE ParentCompanyID in (9)
    UNION ALL
-- Recursive member definition
    SELECT e.ParentCompanyID, e.CompanyID, Levels  + 1, CAST(Concat(d.RowNumber, CAST((Row_Number() Over (Order by e.CompanyName) ) as VARCHAR(MAX)) ) as VARCHAR(MAX)) as RowNumber
    FROM tblCompany AS e   
    INNER JOIN tableR AS d
        ON e.ParentCompanyID = d.CompanyID
)
-- Statement that executes the CTE
SELECT tabler.Levels, RowNumber, tableR.CompanyID, (left('--------------', ((tabler.Levels - 1)* 2 )) + c.CompanyName) as CName,c.ParentCompanyID
FROM tableR  Left join tblcompany c on tableR.CompanyId=c.CompanyID order by RowNumber 

但如果任何级别的记录超过9条,则会失败

嗯,事情是这样的,你没有ORDERBY子句

为什么不试试呢

-- Statement that executes the CTE
SELECT tabler.Levels, tableR.CompanyID, (left('--------------', (tabler.Levels* 2)) + c.CompanyName) as CName,c.ParentCompanyID
FROM tableR  Left join tblcompany c on tableR.CompanyId=c.CompanyID
ORDER BY tableR.Levels
也就是说,显示/UISectioin可能应该由UI输出而不是查询决定


这几乎像是你想把它放在树状视图中,而不是。好了,我终于找到了解决问题的办法。为了得到批评,如果我在这里帮助别人是正确的话

WITH tableR (ParentCompanyID, CompanyID, Levels, RowNumber, RowNumber2)
AS
(
-- Anchor member definition
    SELECT e.ParentCompanyID, e.CompanyID, 1 As Levels, CAST((Row_Number() Over (Order by e.CompanyName) ) as Varchar(MAx)) as RowNumber,
    CAST(
     (Left('000', 3-Len(CAST((Row_Number() Over (Order by e.CompanyName) ) as Varchar(MAx)))) + CAST((Row_Number() Over (Order by e.CompanyName) ) as Varchar(MAx))) 
     As VARCHAR(MAX)
     ) AS RowNumber2
    FROM tblCompany AS e   
    WHERE ParentCompanyID in (370)
    UNION ALL
-- Recursive member definition
    SELECT e.ParentCompanyID, e.CompanyID, Levels  + 1, CAST((Row_Number() Over (Order by e.CompanyName) ) as Varchar(MAx)) as RowNumber1,
    CAST(
        Concat(d.RowNumber2, 
         Left('000', 3-Len(CAST((Row_Number() Over (Order by e.CompanyName) ) as Varchar(MAx)))),
          CAST((Row_Number() Over (Order by e.CompanyName) ) as Varchar(MAx))
        ) as VARCHAR(MAX)) as RowNumber2

    FROM tblCompany AS e   
    INNER JOIN tableR AS d
        ON e.ParentCompanyID = d.CompanyID

)
-- Statement that executes the CTE
SELECT tabler.Levels, RowNumber, RowNumber2,  tableR.CompanyID, (left('--------------', ((tabler.Levels - 1)* 2 )) + c.CompanyName) as CName,c.ParentCompanyID
FROM tableR  Left join tblcompany c on tableR.CompanyId=c.CompanyID order by RowNumber2, CName  
现在,解释如下:

  • 我在SQLServer中添加了一个行数函数,这只需将计数器添加到每一行查询中,就可以为锚定查询和递归查询添加单独的计数器
  • 但由于我们必须对它们进行排列,所以我将父/锚查询值附加到子查询,所以锚查询的顺序是1、2、3。。但孩子11岁,12岁。。。21
  • 然后我将它们转换为字符串,因为按照字符串顺序,您将有1,2,21,3,而不是1,2,3,21。。所以这对我来说很好 已知的问题:当您点击锚查询输出>10行,或影响任何超过10行的行时,它会被忽略,因为锚查询将ID设为11,子查询将变为111并混淆输出

    以上问题的解决方案:我修改我的查询使用LEFT和append 000,所以如果我看到最多可以有100个child,我会将3置零,如果看到4,则使用0000,并在查询中将3更改为4

    但是:我强烈建议您回答上述问题,因为这是解决问题的方法。尝试以下解决方案:

    DECLARE @Company TABLE
    (
        CompanyID INT PRIMARY KEY,
        Name NVARCHAR(50) NOT NULL,
        ParentCompanyID INT NULL
    );
    INSERT @Company (CompanyID,Name,ParentCompanyID)
    VALUES 
    (8,N'Tomaten',NULL),
    (9,N'NON ĂNŞI chars',NULL),
    (10,N'Bananen',NULL),
    (11,N'Child #1',9),
    (12,N'Child #2',9),
    (13,N'Child #1.1',11),
    (14,N'Child #1.2',11);
    
    DECLARE @ParentCompanyID INT = 9;
    WITH RecComp
    AS
    (
        SELECT  crt.CompanyID,
                crt.Name,
                crt.ParentCompanyID,
                1 AS Lvl,
                N'/' + CONVERT(NVARCHAR(4000),crt.CompanyID) + N'/' AS CompanyNode_AsChar
        FROM    @Company crt
        WHERE   crt.ParentCompanyID = @ParentCompanyID
        UNION ALL
        SELECT  cld.CompanyID,
                cld.Name,
                cld.ParentCompanyID,
                prt.Lvl + 1,
                prt.CompanyNode_AsChar + CONVERT(NVARCHAR(4000), cld.CompanyID) + N'/'
        FROM    RecComp prt -- parent
        INNER JOIN @Company cld ON prt.CompanyID = cld.ParentCompanyID
    )
    SELECT  *,
            CONVERT(HIERARCHYID, CompanyNode_AsChar) AS CompanyNode
    FROM    RecComp
    ORDER BY CompanyNode;
    
    结果:

    CompanyID Name       ParentCompanyID Lvl CompanyNode_AsChar CompanyNode
    --------- ---------- --------------- --- --------------------- -----------
    11        Child #1   9               1   /11/                  0xAE
    13        Child #1.1 11              2   /11/13/               0xAF6C
    14        Child #1.2 11              2   /11/14/               0xAF74
    12        Child #2   9               1   /12/                  0xB2
    

    注意:

    我想与大家分享一下

    如果您想订购de数据。。。字母和子数据位于其父数据的正下方。。创建一个baseCTE,使用row_number而不是CompanyID,从baseCTE调用锚查询

    基础热膨胀系数

    ROW_NUMBER() OVER ( PARTITION BY ParentCompanyID ORDER BY CompanyName) as [row_number]
    
    锚查询

    N'/' + CONVERT(NVARCHAR(4000),[row_number]) + N'/' AS CompanyNode_AsChar
    
    递归查询

    prt.CompanyNode_AsChar + CONVERT(NVARCHAR(4000), [row_number]) + N'/'
    

    我添加了orderby,但是它只显示了level1,level2,level3,没有排列它们。作为我的愿望输出。1)哪个SQL Server版本?2) (9)谓词中的
    WHERE ParentCompanyID的目的是什么?是否要显示母公司9的所有子公司?我们有SQL Azure作为服务器。是的,我们需要父ID为9的所有子级。它可以是0来显示所有[我们使用0作为基本级别的父级]。这看起来很棒,我将使用它。。我不知道Hirrachyd,今天要学的新东西。顺便说一句,我修改了自己的解决方案,使之也适用于999儿童:)。但是你的更干净。@SumitGupta:我用SQLServer2008R2测试了这个解决方案。我将在5分钟后在azure上测试