Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Server Equivalent of Oracle 'CONNECT BY PRIOR', and 'ORDER SIBLINGS BY'

I've got this Oracle code structure I'm trying to convert to SQL Server 2008 (Note: I have used generic names, enclosed column names and table names within square brackets '[]', and done some formatting to make the code more readable):

SELECT [col#1], [col#2], [col#3], ..., [col#n], [LEVEL] 
FROM (SELECT [col#1], [col#2], [col#3], ..., [col#n] 
      FROM [TABLE_1] 
      WHERE ... ) 
CONNECT BY PRIOR [col#1] = [col#2] 
START WITH [col#2] IS NULL 
ORDER SIBLINGS BY [col#3]

What is the SQL Server equivalent template of the above code?

Specifically, I'm struggling with the LEVEL, and 'ORDER SIBLINGS BY' Oracle constructs.

Note: The above "code" is the final output from a set of Oracle procedures. Basically, the 'WHERE' clause is built up dynamically and changes depending on various parameters passed. The code block starting with 'CONNECT BY PRIOR' is hard-coded.


For Reference:

The Simulation of CONNECT BY PRIOR of ORACLE in SQL SERVER article comes close, but it does not explain how to handle the 'LEVEL' and the 'ORDER SIBLINGS' constructs. ... And my mind is getting in a twist!

SELECT name 
  FROM emp
  START WITH name = 'Joan'
  CONNECT BY PRIOR empid = mgrid

equates to:

WITH n(empid, name) AS 
   (SELECT empid, name 
    FROM emp
    WHERE name = 'Joan'
        UNION ALL
    SELECT nplus1.empid, nplus1.name 
    FROM emp as nplus1, n
    WHERE n.empid = nplus1.mgrid)
SELECT name FROM n

If I have an initial template to work from, it will go a long way to helping me construct SQL Server stored procs to build up a correct T-SQL statement.

Assistance will be much appreciated.

like image 973
user1058946 Avatar asked Aug 05 '15 08:08

user1058946


People also ask

What is connect by in SQL Server?

CONNECT BY specifies the relationship between the parent rows and child rows of the hierarchy. The NOCYCLE parameter instructs the database to return rows from a query even if a cyclic relation (CONNECT BY LOOP) exists in the data.

How do I create a hierarchical query in SQL Server?

Use hierarchyid as a data type to create tables with a hierarchical structure, or to describe the hierarchical structure of data that is stored in another location. Use the hierarchyid functions in Transact-SQL to query and manage hierarchical data.

What is connect by Prior in SQL?

CONNECT BY: It specifies the relationship between parent rows and child rows of the hierarchy. PRIOR: It's a unary operator and it is used to achieve the recursive condition i.e the actual walking.

Can you link an Oracle Database to SQL Server?

Follow the steps below to link your Oracle to SQL Server right from the Object Explorer pane: On the Management Studio, choose your SQL Server Instance. Click on the Server Objects from the Object Explorer pane and select Linked Servers, then New Linked Server.


1 Answers

Simulating the LEVEL column

The level column can easily be simulated by incrementing a counter in the recursive part:

WITH tree (empid, name, level) AS  (
  SELECT empid, name, 1 as level
  FROM emp
  WHERE name = 'Joan'

  UNION ALL

  SELECT child.empid, child.name, parent.level + 1
  FROM emp as child
    JOIN tree parent on parent.empid = child.mgrid
)
SELECT name 
FROM tree;

Simulating order siblings by

Simulating the order siblings by is a bit more complicated. Assuming we have a column sort_order that defines the order of elements per parent (not the overall sort order - because then order siblings wouldn't be necessary) then we can create a column which gives us an overall sort order:

WITH tree (empid, name, level, sort_path) AS  (
  SELECT empid, name, 1 as level, 
         cast('/' + right('000000' + CONVERT(varchar, sort_order), 6) as varchar(max))
  FROM emp
  WHERE name = 'Joan'

  UNION ALL

  SELECT child.empid, child.name, parent.level + 1, 
         parent.sort_path + '/' + right('000000' + CONVERT(varchar, child.sort_order), 6) 
  FROM emp as child
    JOIN tree parent on parent.empid = child.mgrid
)
SELECT * 
FROM tree
order by sort_path;

The expression for the sort_path looks so complicated because SQL Server (at least the version you are using) does not have a simple function to format a number with leading zeros. In Postgres I would use an integer array so that the conversion to varchar isn't necessary - but that doesn't work in SQL Server either.

like image 136
a_horse_with_no_name Avatar answered Sep 19 '22 16:09

a_horse_with_no_name