无法理解此SQL代码中sortpath列的执行

时间:2018-09-28 06:16:10

标签: sql-server recursion common-table-expression

CREATE FUNCTION dbo.GetSubtree(@mgr AS INT, @maxlevels AS INT = NULL)
  RETURNS TABLE
  WITH SCHEMABINDING
  AS
   RETURN
    WITH EmpsCTE AS
      (
       SELECT empid, CAST(NULL AS INT) AS mgrid, empname, salary, 0 as lvl,
           CAST(‘.’ AS VARCHAR(900)) AS sortpath
           FROM dbo.Employees
            WHERE empid = @mgr
  UNION ALL
   SELECT S.empid, S.mgrid, S.empname, S.salary, M.lvl + 1 AS lvl,
      CAST(M.sortpath + CAST(S.empid AS VARCHAR(10)) + ‘.’ AS VARCHAR(900)) 
      AS sortpath
         FROM EmpsCTE AS M
          INNER JOIN dbo.Employees AS S
            ON S.mgrid = M.empid
           AND (M.lvl < @maxlevels OR @maxlevels IS NULL)
            )
            SELECT empid, mgrid, empname, salary, lvl, sortpath
             FROM EmpsCTE;

这是我在SQL Server中的功能,但是当我使用以下查询执行此操作时,我无法理解sortpath列的输出

SELECT empid, REPLICATE(‘ | ‘, lvl) + empname AS emp,
        mgrid, salary, lvl, sortpath
       FROM dbo.GetSubtree(3, NULL) AS T
        ORDER BY sortpath;

则输出为

empid empname        mgrid  salary   lvl sortpath
------ ----------------- ------ -------- ---- -----------
  3     Ina           NULL  7500.00   0     .
  7     | Aaron       3     5000.00   1     .7.
  11    | | Gabriel   7     3000.00   2     .7.11.
  9     | | Rita      7     3000.00   2     .7.9.
  12    | | | Emilia  9     2000.00   3     .7.9.12.
  13    | | | Michael 9     2000.00   3     .7.9.13.
  14    | | | Didi    9     1500.00   3     .7.9.14.

现在从我的角度来看,具有Empid 11的行应该只有.11。执行此操作的人,我可以

1 个答案:

答案 0 :(得分:0)

  

从我的角度来看,具有Empid 11的行应该只有.11。排序路径的输出

您为什么这么认为?每个员工都加入了他们的经理,并使用他们自己的员工ID和sortpath扩展了经理的.。由于11的经理是7,而7的排序路径是.7.,为什么不期望7在那呢?

如果顾名思义,这打算用于排序,我将使用/作为分隔符,而不是.。我还将在其排序路径中包括顶级经理的id,最后在函数的最终输出中将此列转换为hierarchyid。这样,就可以将/3/7/11/ 之后 /3/7/9/正确排序(与您的输出不同),因为它不仅依赖于字典顺序。

例如:

CREATE FUNCTION dbo.GetSubtree(@mgr AS INT, @maxlevels AS INT = NULL)
  RETURNS TABLE
  WITH SCHEMABINDING
  AS
   RETURN
    WITH EmpsCTE AS
      (
       SELECT empid, CAST(NULL AS INT) AS mgrid, empname, salary, 0 as lvl,
           CAST('/' + s.empid + '/' AS VARCHAR(900)) AS sortpath
           FROM dbo.Employees
            WHERE empid = @mgr
  UNION ALL
   SELECT S.empid, S.mgrid, S.empname, S.salary, M.lvl + 1 AS lvl,
      CAST(M.sortpath + CAST(S.empid AS VARCHAR(10)) + '/' AS VARCHAR(900)) 
      AS sortpath
         FROM EmpsCTE AS M
          INNER JOIN dbo.Employees AS S
            ON S.mgrid = M.empid
           AND (M.lvl < @maxlevels OR @maxlevels IS NULL)
            )
            SELECT empid, mgrid, empname, salary, lvl,
               CAST(sortpath as hierarchyid) as sortpath
             FROM EmpsCTE;