将ORACLE分层START WITH / CONNECT BY转换为SQL Server CTE

时间:2016-05-26 07:40:06

标签: sql sql-server

我无法将当前的ORACLE脚本转换为等效的MS SQL Server版本 - 以便实现相同的功能。

我所做的所有研究都指出CTE是唯一的解决方案,而且我已经完成了大部分工作。唯一剩下的问题是序列不正确 - 因此我的意思是'层次结构'没有正确出现。我已经尝试使用ORDER BY将结果集放到行中,然后尝试ROW_NUMBER()等,但这些方法都没有完全奏效。我认为主要的问题是脚本没有像Oracle脚本那样在层次上进行解析 - 然后我试图'纠正'在CTE完成之后将我挖到更深的洞。

以下是2个脚本;

CURRENT ORACLE SQL SCRIPT VERSION(完美运行)

SELECT lpad('-',2*(level-2), '-') || l.lcname descr, r.lrlocuri1 id, l.lciswithin, l.lctype, 1 lcisactive, l.lcvalidto 
    FROM tslocrel r,  tslocation l WHERE l.uri=r.lrlocuri1
    AND level>1 AND level<6
    AND lctype=1 AND lcvalidto<'2' 
START WITH lrlocuri1=4485 CONNECT BY PRIOR lrlocuri1 = lrlocuri2 

我的MS SQL SERVER VERSION WIP ATTEMPT(SQL 2012是目标版本)

WITH locationCTE (lcname, lrlocuri1, lciswithin, lctype, lcisactive, lcvalidto, level) AS (

  SELECT l.lcname, r.lrlocuri1, l.lciswithin, l.lctype, 1 AS lcisactive, l.lcvalidto, 1 AS level
  FROM tslocrel r
  INNER JOIN tslocation l ON r.lrlocuri1 = l.uri
  AND r.lrlocuri1=4485

  UNION ALL

  SELECT l.lcname, r.lrlocuri1, l.lciswithin, l.lctype, 1 AS lcisactive, l.lcvalidto, cte.level + 1 AS level
  FROM tslocrel r
  INNER JOIN tslocation l ON r.lrlocuri1 = l.uri
  INNER JOIN locationCTE cte ON cte.lrlocuri1 = r.lrlocuri2

)

SELECT RIGHT(REPLICATE('-', 2*(level-2)) + LEFT('-', 2*(level-2)), 2*(level-2)) + lcname AS descr, lrlocuri1 id, lciswithin, lctype, lcisactive, 
lcvalidto
FROM locationCTE
WHERE level>1 AND level<6
AND lctype=1 AND lcvalidto<'2'

我尝试过其他一些尝试,基本上会继续回到相同的结果。 这些查询在TRIM数据库上运行,并且应该通过向下导航到lrlocuri1和lrlocuri2来列出“位置”的层次结构,例如如下所示;

General Manager
  -Corporate Support
    --Customer Service
      --Xxxxxxx
      --Xxxxxxx
      (etc)
    --Finance
      --Xxxxx
  -Environment and Planning
    --Xxxxx
    --Xxxxx
  -Xxxxxxxxxxxx
    --Xxxxx
    --XXxxx

1 个答案:

答案 0 :(得分:0)

Oracle定义按深度优先顺序返回层次结构数据集。因此,您在此处的订购是正确的(例如https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm)。

另一方面,

SqlServer没有这个结果集排序。您必须自己订购数据行。我的解决方案是为每一行构建一个分层路径值,以便在选择数据后进行排序。如果你有每行的id值,就像这样

parent-id / child-id

以下是一个很好的示例:Controlling the sibling order under recursive CTE?(查看列路径)。

如果有其他SQLServer解决方案可能,主要是针对它的更新版本,我很想知道。