0

Hello I have this part of a view in an Oracle database and I must change it on Microsoft Sql Server.

with V_LOCHIERARHY_N
(nr, nivel, location, parent, systemid, siteid, orgid, count_a, count_wo, children)
AS
SELECT     LEVEL, LPAD (' ', 2 * (LEVEL - 1)) || l.LOCATION nivel,
              LOCATION, PARENT, systemid, siteid, orgid,
             (SELECT COUNT (a.ancestor)
             FROM locancestor a
            WHERE a.LOCATION = l.LOCATION AND a.siteid = l.siteid),
                  NVL (COUNT (w.wonum), 0)
             FROM maximo.workorder w

            WHERE  (    w.reportdate >
                          TO_TIMESTAMP ('2006-06-19 00:00:01',
                                        'YYYY-MM-DD HH24:MI:SS.FF'
                                       )
                   AND w.istask = 0
                   AND w.worktype <> 'P'
                   AND w.LOCATION = l.LOCATION
                  )
              AND w.status <> 'CAN'),
          l.children
     FROM lochierarchy l
    START WITH l.LOCATION = 'StartPoint'
   CONNECT BY PRIOR l.LOCATION = l.PARENT AND l.siteid = 'SiteTest'

What I need from this script is to return all the children of a given entry (the description of the children which can be found in locations table).

I have a table with next columns:

Location Parent      Systemid Children Siteid Origid Lochierarchyid
A001     StartPoint  Primary  2        SiteTest    X      106372
A002     A001        Primary  2        SiteTest    X      105472
A003     A002        Primary  0        SiteTest    X      98654
A004     A002        Primary  1        SiteTest    X      875543
A004B    A004        Primary  0        SiteTest    X      443216
B005     StartPoint  Primary  0        SiteTest    X      544321

For example for given entry A001 will return


A002    
 A003     
 A004
  A004B     
B005 

I have made this view below but I don't know how to integrate it with the first one. Also it doesn't return me the list in the corectly order

Parent  
 Children 1 of parent
  Children a of children 1
  children b of children 1
 children 2 of parent
  children a1 of children 2 and so on.

 WITH testCTE AS
(
     SELECT l.parent, l.location as child, l.location, l.lochierarchyid
     FROM lochierarchy l
     where location='SecondLocation' --and siteid='SiteTest'
       UNION ALL
     SELECT c.Parent, l.parent, l.location, l.lochierarchyid
     FROM lochierarchy l 
    INNER JOIN testCTE c ON l.parent = c.location
 )
  SELECT  *
  FROM testCTE c
  order BY c.parent,child asc
 ;

Can please someone help me? :)

Madalina
  • 85
  • 2
  • 15
  • If I have some time, I will work on a solution. You may also be able to figure it out on your own, with some help. The article below shows, step by step, how to reproduce all the features of a "connect by" query with recursive subquery factoring: https://oracle-base.com/articles/11g/recursive-subquery-factoring-11gr2 –  Feb 21 '17 at 12:55
  • Please do *not* vandalise your posts. – Martijn Pieters Mar 07 '17 at 10:19
  • Possible duplicate of [How to UPDATE from a SELECT in SQL Server?](http://stackoverflow.com/questions/2334712/how-to-update-from-a-select-in-sql-server) – Madalina Apr 03 '17 at 12:19

2 Answers2

1

Following the query proposed by mathguy, modified for MSSQL (2012)

    with
         inputs ( location, parent ) as (
           select 'A001' , 'StartPoint' union all
           select 'A002' , 'A001'       union all
           select 'A003' , 'A002'       union all
           select 'A004' , 'A002'       union all
       select 'A004B', 'A004'       union all
       select 'B005' , 'StartPoint' 
     ),
     r (lvl, location, ord ) as (
       select  1, location, CAST(location AS VARCHAR(400))
         from  inputs
         where parent = 'StartPoint'
       union all
       select  r.lvl + 1, i.location, CAST(r.location + '/' + i.location AS VARCHAR(400))
         from  r join inputs i on r.location = i.parent
     )
select REPLICATE(' ', 2 * (lvl-1)) + location as location
from   r
order by ord
;

Ouput:

location
-------------------------------------------------------------------
A001
  A002
    A003
    A004
      A004B
B005
Madalina
  • 85
  • 2
  • 15
etsa
  • 5,020
  • 1
  • 7
  • 18
0

Here is how you can do this (in Oracle, the only flavor I know) using a recursive query. "The web" reports SQL Server implements recursive queries as well, and with the same syntax (I believe all of this is SQL Standard compliant, so that's not surprising). Give it a try.

Instead of creating a table, I put all the test data in the first CTE. When you try this solution, delete the CTE named inputs first, and use your actual table name in the rest of the query.

with
     inputs ( location, parent ) as (
       select 'A001' , 'Downstream' from dual union all
       select 'A002' , 'A001'       from dual union all
       select 'A003' , 'A002'       from dual union all
       select 'A004' , 'A002'       from dual union all
       select 'A004B', 'A004'       from dual union all
       select 'B005' , 'Downstream' from dual
     ),
     r ( lvl, location ) as (
       select  1, location
         from  inputs
         where parent = 'Downstream'
       union all
       select  r.lvl + 1, i.location
         from  r join inputs i on r.location = i.parent
     )
     search depth first by lvl set ord
select lpad(' ', 2 * (lvl-1), ' ') || location as location
from   r
order by ord
;


LOCATION
--------------------
A001
  A002
    A003
    A004
      A004B
B005

6 rows selected.

ADDED: It seems SQL Server doesn't have the search depth/breadth first clause for recursive CTE's (or perhaps the syntax is different). In any case, here is a primitive "manual" implementation of the same:

with  (   .........   ),
     r ( lvl, location, ord ) as (
       select  1, location, location
         from  inputs
         where parent = 'Downstream'
       union all
       select  r.lvl + 1, i.location, r.location || '/' || i.location
         from  r join inputs i on r.location = i.parent
     )
select lpad(' ', 2 * (lvl-1), ' ') || location as location
from   r
order by ord
;
  • @AndreeaEnache - Perhaps SQL Server does not have the SEARCH clause for recursive queries (or perhaps the syntax is different). I don't have SQL Server, but: please try again after you comment out that line and the ORDER BY clause at the very end. Does the rest work? If it does, you can research the equivalent of SEARCH DEPTH FIRST for SQL Server; I will think a bit to see what the correct formula is for the `ord` in my query (the same formula, I'm sure, that Oracle uses to get the ordering correct). –  Feb 24 '17 at 20:20
  • @AndreeaEnache - OK, I added to my answer: I implemented a rudimentary "search depth first" from scratch. –  Feb 24 '17 at 20:32
  • :-) This is why you need help from someone who knows both Oracle and SQL Server... yes, `||` is concatenation in Oracle, not sure what SQL Server uses. For the error you get: I assume it's for the `ord` thing, and I further assume your LOCATION is not actually a string. Right? If it's a NUMBER, that would cause a problem because I treat it as a string, with no conversions. If it's a NUMBER then ord is a NUMBER in the anchor but it becomes a string after concatenation in the recursive branch. If indeed your location is a number (of some SQL Server kind), wrap it within TO_CHAR() or equivalent. –  Feb 24 '17 at 21:03
  • @AndreeaEnache - See above. Actually you already said it's for `ord`, I just missed it the first time I read it. –  Feb 24 '17 at 21:04
  • @AndreeaEnache - If you are able to find a fully functioning SQL Server solution, it would definitely help others in the future if you would post it here. You **are** allowed (and even encouraged) to post answers to your own questions on Stack Overflow, precisely for that purpose. –  Feb 24 '17 at 21:48