SQL - get all parents/childs?












1















hopefully someone can help with this. I have recieved a table of data which I need to restructure and build a Denorm table out of. The table structure is as follows



UserID     Logon    ParentID 
2344 Test1 2000
2345 Test2 2000


The issue I have is the ParentID is also a UserID of its own and in the same table.



SELECT * FROM tbl where ParentID=2000 gives the below output



UserID     Logon      ParentID 
2000 Test Team 2500


Again, the ParentID of this is also stored as a UserID..



SELECT * FROM tbl where ParentID=2500 gives the below output



UserID     Logon            ParentID 
2500 Test Division NULL


I want a query that will pull all of these relationships and the logons into one row, with my output looking like the below.



 UserID   Username       Parent1        Parent2        Parent3     Parent4
2344 Test1 Test Team Test Division NULL NULL
2345 Test2 Test Team Test Division NULL NULL


The maximum number of parents a user can have is 4, in this case there is only 2. Can someone help me with the query needed to build this?



Appreciate any help
Thanks
Jess










share|improve this question























  • Please show us what you have tried, and why its not working.

    – Dave Cullum
    Nov 22 '18 at 15:13











  • One solution I found had the parents and childIDs on separate table which isn't the case here. i wouldn't know where to start with the above as I am not too advanced

    – Jess8766
    Nov 22 '18 at 15:15











  • Have a look at recursive cte. An application is in this link: stackoverflow.com/questions/959804/….

    – Mischa Vreeburg
    Nov 22 '18 at 16:26


















1















hopefully someone can help with this. I have recieved a table of data which I need to restructure and build a Denorm table out of. The table structure is as follows



UserID     Logon    ParentID 
2344 Test1 2000
2345 Test2 2000


The issue I have is the ParentID is also a UserID of its own and in the same table.



SELECT * FROM tbl where ParentID=2000 gives the below output



UserID     Logon      ParentID 
2000 Test Team 2500


Again, the ParentID of this is also stored as a UserID..



SELECT * FROM tbl where ParentID=2500 gives the below output



UserID     Logon            ParentID 
2500 Test Division NULL


I want a query that will pull all of these relationships and the logons into one row, with my output looking like the below.



 UserID   Username       Parent1        Parent2        Parent3     Parent4
2344 Test1 Test Team Test Division NULL NULL
2345 Test2 Test Team Test Division NULL NULL


The maximum number of parents a user can have is 4, in this case there is only 2. Can someone help me with the query needed to build this?



Appreciate any help
Thanks
Jess










share|improve this question























  • Please show us what you have tried, and why its not working.

    – Dave Cullum
    Nov 22 '18 at 15:13











  • One solution I found had the parents and childIDs on separate table which isn't the case here. i wouldn't know where to start with the above as I am not too advanced

    – Jess8766
    Nov 22 '18 at 15:15











  • Have a look at recursive cte. An application is in this link: stackoverflow.com/questions/959804/….

    – Mischa Vreeburg
    Nov 22 '18 at 16:26
















1












1








1








hopefully someone can help with this. I have recieved a table of data which I need to restructure and build a Denorm table out of. The table structure is as follows



UserID     Logon    ParentID 
2344 Test1 2000
2345 Test2 2000


The issue I have is the ParentID is also a UserID of its own and in the same table.



SELECT * FROM tbl where ParentID=2000 gives the below output



UserID     Logon      ParentID 
2000 Test Team 2500


Again, the ParentID of this is also stored as a UserID..



SELECT * FROM tbl where ParentID=2500 gives the below output



UserID     Logon            ParentID 
2500 Test Division NULL


I want a query that will pull all of these relationships and the logons into one row, with my output looking like the below.



 UserID   Username       Parent1        Parent2        Parent3     Parent4
2344 Test1 Test Team Test Division NULL NULL
2345 Test2 Test Team Test Division NULL NULL


The maximum number of parents a user can have is 4, in this case there is only 2. Can someone help me with the query needed to build this?



Appreciate any help
Thanks
Jess










share|improve this question














hopefully someone can help with this. I have recieved a table of data which I need to restructure and build a Denorm table out of. The table structure is as follows



UserID     Logon    ParentID 
2344 Test1 2000
2345 Test2 2000


The issue I have is the ParentID is also a UserID of its own and in the same table.



SELECT * FROM tbl where ParentID=2000 gives the below output



UserID     Logon      ParentID 
2000 Test Team 2500


Again, the ParentID of this is also stored as a UserID..



SELECT * FROM tbl where ParentID=2500 gives the below output



UserID     Logon            ParentID 
2500 Test Division NULL


I want a query that will pull all of these relationships and the logons into one row, with my output looking like the below.



 UserID   Username       Parent1        Parent2        Parent3     Parent4
2344 Test1 Test Team Test Division NULL NULL
2345 Test2 Test Team Test Division NULL NULL


The maximum number of parents a user can have is 4, in this case there is only 2. Can someone help me with the query needed to build this?



Appreciate any help
Thanks
Jess







sql sql-server-2012






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 22 '18 at 15:08









Jess8766Jess8766

667




667













  • Please show us what you have tried, and why its not working.

    – Dave Cullum
    Nov 22 '18 at 15:13











  • One solution I found had the parents and childIDs on separate table which isn't the case here. i wouldn't know where to start with the above as I am not too advanced

    – Jess8766
    Nov 22 '18 at 15:15











  • Have a look at recursive cte. An application is in this link: stackoverflow.com/questions/959804/….

    – Mischa Vreeburg
    Nov 22 '18 at 16:26





















  • Please show us what you have tried, and why its not working.

    – Dave Cullum
    Nov 22 '18 at 15:13











  • One solution I found had the parents and childIDs on separate table which isn't the case here. i wouldn't know where to start with the above as I am not too advanced

    – Jess8766
    Nov 22 '18 at 15:15











  • Have a look at recursive cte. An application is in this link: stackoverflow.com/questions/959804/….

    – Mischa Vreeburg
    Nov 22 '18 at 16:26



















Please show us what you have tried, and why its not working.

– Dave Cullum
Nov 22 '18 at 15:13





Please show us what you have tried, and why its not working.

– Dave Cullum
Nov 22 '18 at 15:13













One solution I found had the parents and childIDs on separate table which isn't the case here. i wouldn't know where to start with the above as I am not too advanced

– Jess8766
Nov 22 '18 at 15:15





One solution I found had the parents and childIDs on separate table which isn't the case here. i wouldn't know where to start with the above as I am not too advanced

– Jess8766
Nov 22 '18 at 15:15













Have a look at recursive cte. An application is in this link: stackoverflow.com/questions/959804/….

– Mischa Vreeburg
Nov 22 '18 at 16:26







Have a look at recursive cte. An application is in this link: stackoverflow.com/questions/959804/….

– Mischa Vreeburg
Nov 22 '18 at 16:26














4 Answers
4






active

oldest

votes


















2














You can use basicly LEFT JOIN. If you have static 4 parent it should work. If you have unknown parents you should do dynamic query.



SELECT U1.UserId
,U1.UserName
,U2.UserName AS Parent1
,U3.UserName AS Parent2
,U4.UserName AS Parent3
,U5.UserName AS Parent4
FROM Users U1
LEFT JOIN Users U2 ON U1.ParentId = U2.UserId
LEFT JOIN Users U3 ON U2.ParentId = U3.UserId
LEFT JOIN Users U4 ON U3.ParentId = U4.UserId
LEFT JOIN Users U5 ON U4.ParentId = U5.UserId


EDIT : Additional(to exclude parent users from the list) :



WHERE NOT EXISTS (SELECT 1 FROM Users UC WHERE U1.UserId = UC.ParentId)





share|improve this answer


























  • This works but I get some rows where the Username is the parent1. For example I am seeing "Test Team" as a username with Test Division as parent 1. Is there anyway to exclude these?

    – Jess8766
    Nov 22 '18 at 15:35













  • @Jess8766 if you only want rows for users that are not parents you need to add WHERE U1.UserId NOT IN (SELECT ParentId FROM Users)

    – Dávid Laczkó
    Nov 22 '18 at 15:51











  • @Jess8766 I have added NOT EXISTS condition to the WHERE statement to exclude parent users.

    – Zeki Gumus
    Nov 22 '18 at 16:04



















1














select 
tb1.UserId as UserId,
tb1.UserName as UserName,
tb2.UserName as Parent1,
tb3.UserName as Parent2,
tb4.UserName as Parent3,
tb5.UserName as Parent4
from tbl t1
left join tbl t2 on t2.UserId=t1.ParentID
left join tbl t3 on t3.UserId=t2.ParentID
left join tbl t4 on t4.UserId=t3.ParentID
left join tbl t5 on t5.UserId=t4.ParentID;


you need to do 4 left joins in order to fetch 4 parent details






share|improve this answer

































    0














    Use a recursive CTE to get the levels then pivot to put them in columns:



    WITH cte(UserID, Logon, ParentID, ParentLogon, ParentLevel) AS
    (
    SELECT UserID, Logon, ParentID, Logon, 0
    FROM users
    UNION ALL
    SELECT u.UserID, u.Logon, u.ParentID, cte.ParentLogon, ParentLevel + 1
    FROM users u
    JOIN cte ON cte.UserID = u.ParentID
    )
    SELECT UserId, Logon, Parent1, Parent2, Parent3, Parent4 FROM cte
    PIVOT (
    MAX(ParentLogon)
    FOR ParentLevel
    IN (
    1 AS Parent1,
    2 AS Parent2,
    3 AS Parent3,
    4 AS Parent4
    )
    )


    See SQL Fiddle example






    share|improve this answer

































      0














      In order to get all parent or child, it's efficient to use a recursive function which would fetch the whole hierarchy.



      Sample Table:



      CREATE TABLE #TEST
      (
      [Name] varchar(100),
      ManagerName Varchar(100),
      Number int
      )


      Insert some values



      Insert into Test values
      ('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('f','g')


      Create recursive function as below



      CREATE FUNCTION [dbo].[fnRecursive] (@EmpName Varchar(100), @incremental int)
      RETURNS @ret TABLE
      (

      ManagerName varchar(100),
      Number int
      )
      AS
      BEGIN
      Declare @MgrName varchar(100)

      SET @MgrName = (Select ManagerName from test where [name] = @EmpName)

      Insert into @ret values (@MgrName, @incremental)
      if(@MgrName is not null)
      BEGIN
      SET @incremental = @incremental + 1;
      Insert into @ret
      Select ManagerName, Number from [fnRecursive](@MgrName, @incremental)

      END

      RETURN;
      END


      If this function is joined with table, it should list the hierarchy for all employees



      CREATE TABLE #TEST
      (
      [Name] varchar(100),
      ManagerName Varchar(100),
      Number int
      )



      Insert into #TEST
      Select x.[Name], x.ManagerName,x.number from (
      select t.[Name],a.ManagerName as managerName, a.number as number from TEST t outer apply
      (
      select * from [fnRecursive](t.[Name],1)
      ) a)
      x

      Select * from #Test


      If we do a pivot on the table (excluding the 'Number' column). Assuming we store in the table "#temp" it should list all the managers as a column.



       DECLARE @cols AS NVARCHAR(MAX),
      @query AS NVARCHAR(MAX);

      SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[ManagerName] )
      FROM #temp c
      FOR XML PATH(''), TYPE
      ).value('.', 'NVARCHAR(MAX)')
      ,1,1,'')



      set @query = 'select * from #temp
      pivot
      (
      min([managername])
      for managername in (' + @cols + ')
      ) p '

      execute(@query)


      But this doesn't name the column as 'Parent1', 'Parent2' instead with the dynamic column name.



      Link below should help to set custom column name for the dynamic pivot table



       https://stackoverflow.com/questions/16614994/sql-server-pivot-with-custom-column-names





      share|improve this answer

























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433788%2fsql-get-all-parents-childs%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        2














        You can use basicly LEFT JOIN. If you have static 4 parent it should work. If you have unknown parents you should do dynamic query.



        SELECT U1.UserId
        ,U1.UserName
        ,U2.UserName AS Parent1
        ,U3.UserName AS Parent2
        ,U4.UserName AS Parent3
        ,U5.UserName AS Parent4
        FROM Users U1
        LEFT JOIN Users U2 ON U1.ParentId = U2.UserId
        LEFT JOIN Users U3 ON U2.ParentId = U3.UserId
        LEFT JOIN Users U4 ON U3.ParentId = U4.UserId
        LEFT JOIN Users U5 ON U4.ParentId = U5.UserId


        EDIT : Additional(to exclude parent users from the list) :



        WHERE NOT EXISTS (SELECT 1 FROM Users UC WHERE U1.UserId = UC.ParentId)





        share|improve this answer


























        • This works but I get some rows where the Username is the parent1. For example I am seeing "Test Team" as a username with Test Division as parent 1. Is there anyway to exclude these?

          – Jess8766
          Nov 22 '18 at 15:35













        • @Jess8766 if you only want rows for users that are not parents you need to add WHERE U1.UserId NOT IN (SELECT ParentId FROM Users)

          – Dávid Laczkó
          Nov 22 '18 at 15:51











        • @Jess8766 I have added NOT EXISTS condition to the WHERE statement to exclude parent users.

          – Zeki Gumus
          Nov 22 '18 at 16:04
















        2














        You can use basicly LEFT JOIN. If you have static 4 parent it should work. If you have unknown parents you should do dynamic query.



        SELECT U1.UserId
        ,U1.UserName
        ,U2.UserName AS Parent1
        ,U3.UserName AS Parent2
        ,U4.UserName AS Parent3
        ,U5.UserName AS Parent4
        FROM Users U1
        LEFT JOIN Users U2 ON U1.ParentId = U2.UserId
        LEFT JOIN Users U3 ON U2.ParentId = U3.UserId
        LEFT JOIN Users U4 ON U3.ParentId = U4.UserId
        LEFT JOIN Users U5 ON U4.ParentId = U5.UserId


        EDIT : Additional(to exclude parent users from the list) :



        WHERE NOT EXISTS (SELECT 1 FROM Users UC WHERE U1.UserId = UC.ParentId)





        share|improve this answer


























        • This works but I get some rows where the Username is the parent1. For example I am seeing "Test Team" as a username with Test Division as parent 1. Is there anyway to exclude these?

          – Jess8766
          Nov 22 '18 at 15:35













        • @Jess8766 if you only want rows for users that are not parents you need to add WHERE U1.UserId NOT IN (SELECT ParentId FROM Users)

          – Dávid Laczkó
          Nov 22 '18 at 15:51











        • @Jess8766 I have added NOT EXISTS condition to the WHERE statement to exclude parent users.

          – Zeki Gumus
          Nov 22 '18 at 16:04














        2












        2








        2







        You can use basicly LEFT JOIN. If you have static 4 parent it should work. If you have unknown parents you should do dynamic query.



        SELECT U1.UserId
        ,U1.UserName
        ,U2.UserName AS Parent1
        ,U3.UserName AS Parent2
        ,U4.UserName AS Parent3
        ,U5.UserName AS Parent4
        FROM Users U1
        LEFT JOIN Users U2 ON U1.ParentId = U2.UserId
        LEFT JOIN Users U3 ON U2.ParentId = U3.UserId
        LEFT JOIN Users U4 ON U3.ParentId = U4.UserId
        LEFT JOIN Users U5 ON U4.ParentId = U5.UserId


        EDIT : Additional(to exclude parent users from the list) :



        WHERE NOT EXISTS (SELECT 1 FROM Users UC WHERE U1.UserId = UC.ParentId)





        share|improve this answer















        You can use basicly LEFT JOIN. If you have static 4 parent it should work. If you have unknown parents you should do dynamic query.



        SELECT U1.UserId
        ,U1.UserName
        ,U2.UserName AS Parent1
        ,U3.UserName AS Parent2
        ,U4.UserName AS Parent3
        ,U5.UserName AS Parent4
        FROM Users U1
        LEFT JOIN Users U2 ON U1.ParentId = U2.UserId
        LEFT JOIN Users U3 ON U2.ParentId = U3.UserId
        LEFT JOIN Users U4 ON U3.ParentId = U4.UserId
        LEFT JOIN Users U5 ON U4.ParentId = U5.UserId


        EDIT : Additional(to exclude parent users from the list) :



        WHERE NOT EXISTS (SELECT 1 FROM Users UC WHERE U1.UserId = UC.ParentId)






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 22 '18 at 16:02

























        answered Nov 22 '18 at 15:23









        Zeki GumusZeki Gumus

        1,372212




        1,372212













        • This works but I get some rows where the Username is the parent1. For example I am seeing "Test Team" as a username with Test Division as parent 1. Is there anyway to exclude these?

          – Jess8766
          Nov 22 '18 at 15:35













        • @Jess8766 if you only want rows for users that are not parents you need to add WHERE U1.UserId NOT IN (SELECT ParentId FROM Users)

          – Dávid Laczkó
          Nov 22 '18 at 15:51











        • @Jess8766 I have added NOT EXISTS condition to the WHERE statement to exclude parent users.

          – Zeki Gumus
          Nov 22 '18 at 16:04



















        • This works but I get some rows where the Username is the parent1. For example I am seeing "Test Team" as a username with Test Division as parent 1. Is there anyway to exclude these?

          – Jess8766
          Nov 22 '18 at 15:35













        • @Jess8766 if you only want rows for users that are not parents you need to add WHERE U1.UserId NOT IN (SELECT ParentId FROM Users)

          – Dávid Laczkó
          Nov 22 '18 at 15:51











        • @Jess8766 I have added NOT EXISTS condition to the WHERE statement to exclude parent users.

          – Zeki Gumus
          Nov 22 '18 at 16:04

















        This works but I get some rows where the Username is the parent1. For example I am seeing "Test Team" as a username with Test Division as parent 1. Is there anyway to exclude these?

        – Jess8766
        Nov 22 '18 at 15:35







        This works but I get some rows where the Username is the parent1. For example I am seeing "Test Team" as a username with Test Division as parent 1. Is there anyway to exclude these?

        – Jess8766
        Nov 22 '18 at 15:35















        @Jess8766 if you only want rows for users that are not parents you need to add WHERE U1.UserId NOT IN (SELECT ParentId FROM Users)

        – Dávid Laczkó
        Nov 22 '18 at 15:51





        @Jess8766 if you only want rows for users that are not parents you need to add WHERE U1.UserId NOT IN (SELECT ParentId FROM Users)

        – Dávid Laczkó
        Nov 22 '18 at 15:51













        @Jess8766 I have added NOT EXISTS condition to the WHERE statement to exclude parent users.

        – Zeki Gumus
        Nov 22 '18 at 16:04





        @Jess8766 I have added NOT EXISTS condition to the WHERE statement to exclude parent users.

        – Zeki Gumus
        Nov 22 '18 at 16:04













        1














        select 
        tb1.UserId as UserId,
        tb1.UserName as UserName,
        tb2.UserName as Parent1,
        tb3.UserName as Parent2,
        tb4.UserName as Parent3,
        tb5.UserName as Parent4
        from tbl t1
        left join tbl t2 on t2.UserId=t1.ParentID
        left join tbl t3 on t3.UserId=t2.ParentID
        left join tbl t4 on t4.UserId=t3.ParentID
        left join tbl t5 on t5.UserId=t4.ParentID;


        you need to do 4 left joins in order to fetch 4 parent details






        share|improve this answer






























          1














          select 
          tb1.UserId as UserId,
          tb1.UserName as UserName,
          tb2.UserName as Parent1,
          tb3.UserName as Parent2,
          tb4.UserName as Parent3,
          tb5.UserName as Parent4
          from tbl t1
          left join tbl t2 on t2.UserId=t1.ParentID
          left join tbl t3 on t3.UserId=t2.ParentID
          left join tbl t4 on t4.UserId=t3.ParentID
          left join tbl t5 on t5.UserId=t4.ParentID;


          you need to do 4 left joins in order to fetch 4 parent details






          share|improve this answer




























            1












            1








            1







            select 
            tb1.UserId as UserId,
            tb1.UserName as UserName,
            tb2.UserName as Parent1,
            tb3.UserName as Parent2,
            tb4.UserName as Parent3,
            tb5.UserName as Parent4
            from tbl t1
            left join tbl t2 on t2.UserId=t1.ParentID
            left join tbl t3 on t3.UserId=t2.ParentID
            left join tbl t4 on t4.UserId=t3.ParentID
            left join tbl t5 on t5.UserId=t4.ParentID;


            you need to do 4 left joins in order to fetch 4 parent details






            share|improve this answer















            select 
            tb1.UserId as UserId,
            tb1.UserName as UserName,
            tb2.UserName as Parent1,
            tb3.UserName as Parent2,
            tb4.UserName as Parent3,
            tb5.UserName as Parent4
            from tbl t1
            left join tbl t2 on t2.UserId=t1.ParentID
            left join tbl t3 on t3.UserId=t2.ParentID
            left join tbl t4 on t4.UserId=t3.ParentID
            left join tbl t5 on t5.UserId=t4.ParentID;


            you need to do 4 left joins in order to fetch 4 parent details







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 23 '18 at 3:07









            Pawel Czapski

            1,2681917




            1,2681917










            answered Nov 22 '18 at 15:20









            nikhilesh soninikhilesh soni

            111




            111























                0














                Use a recursive CTE to get the levels then pivot to put them in columns:



                WITH cte(UserID, Logon, ParentID, ParentLogon, ParentLevel) AS
                (
                SELECT UserID, Logon, ParentID, Logon, 0
                FROM users
                UNION ALL
                SELECT u.UserID, u.Logon, u.ParentID, cte.ParentLogon, ParentLevel + 1
                FROM users u
                JOIN cte ON cte.UserID = u.ParentID
                )
                SELECT UserId, Logon, Parent1, Parent2, Parent3, Parent4 FROM cte
                PIVOT (
                MAX(ParentLogon)
                FOR ParentLevel
                IN (
                1 AS Parent1,
                2 AS Parent2,
                3 AS Parent3,
                4 AS Parent4
                )
                )


                See SQL Fiddle example






                share|improve this answer






























                  0














                  Use a recursive CTE to get the levels then pivot to put them in columns:



                  WITH cte(UserID, Logon, ParentID, ParentLogon, ParentLevel) AS
                  (
                  SELECT UserID, Logon, ParentID, Logon, 0
                  FROM users
                  UNION ALL
                  SELECT u.UserID, u.Logon, u.ParentID, cte.ParentLogon, ParentLevel + 1
                  FROM users u
                  JOIN cte ON cte.UserID = u.ParentID
                  )
                  SELECT UserId, Logon, Parent1, Parent2, Parent3, Parent4 FROM cte
                  PIVOT (
                  MAX(ParentLogon)
                  FOR ParentLevel
                  IN (
                  1 AS Parent1,
                  2 AS Parent2,
                  3 AS Parent3,
                  4 AS Parent4
                  )
                  )


                  See SQL Fiddle example






                  share|improve this answer




























                    0












                    0








                    0







                    Use a recursive CTE to get the levels then pivot to put them in columns:



                    WITH cte(UserID, Logon, ParentID, ParentLogon, ParentLevel) AS
                    (
                    SELECT UserID, Logon, ParentID, Logon, 0
                    FROM users
                    UNION ALL
                    SELECT u.UserID, u.Logon, u.ParentID, cte.ParentLogon, ParentLevel + 1
                    FROM users u
                    JOIN cte ON cte.UserID = u.ParentID
                    )
                    SELECT UserId, Logon, Parent1, Parent2, Parent3, Parent4 FROM cte
                    PIVOT (
                    MAX(ParentLogon)
                    FOR ParentLevel
                    IN (
                    1 AS Parent1,
                    2 AS Parent2,
                    3 AS Parent3,
                    4 AS Parent4
                    )
                    )


                    See SQL Fiddle example






                    share|improve this answer















                    Use a recursive CTE to get the levels then pivot to put them in columns:



                    WITH cte(UserID, Logon, ParentID, ParentLogon, ParentLevel) AS
                    (
                    SELECT UserID, Logon, ParentID, Logon, 0
                    FROM users
                    UNION ALL
                    SELECT u.UserID, u.Logon, u.ParentID, cte.ParentLogon, ParentLevel + 1
                    FROM users u
                    JOIN cte ON cte.UserID = u.ParentID
                    )
                    SELECT UserId, Logon, Parent1, Parent2, Parent3, Parent4 FROM cte
                    PIVOT (
                    MAX(ParentLogon)
                    FOR ParentLevel
                    IN (
                    1 AS Parent1,
                    2 AS Parent2,
                    3 AS Parent3,
                    4 AS Parent4
                    )
                    )


                    See SQL Fiddle example







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 23 '18 at 10:20

























                    answered Nov 23 '18 at 10:12









                    Andy NAndy N

                    411314




                    411314























                        0














                        In order to get all parent or child, it's efficient to use a recursive function which would fetch the whole hierarchy.



                        Sample Table:



                        CREATE TABLE #TEST
                        (
                        [Name] varchar(100),
                        ManagerName Varchar(100),
                        Number int
                        )


                        Insert some values



                        Insert into Test values
                        ('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('f','g')


                        Create recursive function as below



                        CREATE FUNCTION [dbo].[fnRecursive] (@EmpName Varchar(100), @incremental int)
                        RETURNS @ret TABLE
                        (

                        ManagerName varchar(100),
                        Number int
                        )
                        AS
                        BEGIN
                        Declare @MgrName varchar(100)

                        SET @MgrName = (Select ManagerName from test where [name] = @EmpName)

                        Insert into @ret values (@MgrName, @incremental)
                        if(@MgrName is not null)
                        BEGIN
                        SET @incremental = @incremental + 1;
                        Insert into @ret
                        Select ManagerName, Number from [fnRecursive](@MgrName, @incremental)

                        END

                        RETURN;
                        END


                        If this function is joined with table, it should list the hierarchy for all employees



                        CREATE TABLE #TEST
                        (
                        [Name] varchar(100),
                        ManagerName Varchar(100),
                        Number int
                        )



                        Insert into #TEST
                        Select x.[Name], x.ManagerName,x.number from (
                        select t.[Name],a.ManagerName as managerName, a.number as number from TEST t outer apply
                        (
                        select * from [fnRecursive](t.[Name],1)
                        ) a)
                        x

                        Select * from #Test


                        If we do a pivot on the table (excluding the 'Number' column). Assuming we store in the table "#temp" it should list all the managers as a column.



                         DECLARE @cols AS NVARCHAR(MAX),
                        @query AS NVARCHAR(MAX);

                        SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[ManagerName] )
                        FROM #temp c
                        FOR XML PATH(''), TYPE
                        ).value('.', 'NVARCHAR(MAX)')
                        ,1,1,'')



                        set @query = 'select * from #temp
                        pivot
                        (
                        min([managername])
                        for managername in (' + @cols + ')
                        ) p '

                        execute(@query)


                        But this doesn't name the column as 'Parent1', 'Parent2' instead with the dynamic column name.



                        Link below should help to set custom column name for the dynamic pivot table



                         https://stackoverflow.com/questions/16614994/sql-server-pivot-with-custom-column-names





                        share|improve this answer






























                          0














                          In order to get all parent or child, it's efficient to use a recursive function which would fetch the whole hierarchy.



                          Sample Table:



                          CREATE TABLE #TEST
                          (
                          [Name] varchar(100),
                          ManagerName Varchar(100),
                          Number int
                          )


                          Insert some values



                          Insert into Test values
                          ('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('f','g')


                          Create recursive function as below



                          CREATE FUNCTION [dbo].[fnRecursive] (@EmpName Varchar(100), @incremental int)
                          RETURNS @ret TABLE
                          (

                          ManagerName varchar(100),
                          Number int
                          )
                          AS
                          BEGIN
                          Declare @MgrName varchar(100)

                          SET @MgrName = (Select ManagerName from test where [name] = @EmpName)

                          Insert into @ret values (@MgrName, @incremental)
                          if(@MgrName is not null)
                          BEGIN
                          SET @incremental = @incremental + 1;
                          Insert into @ret
                          Select ManagerName, Number from [fnRecursive](@MgrName, @incremental)

                          END

                          RETURN;
                          END


                          If this function is joined with table, it should list the hierarchy for all employees



                          CREATE TABLE #TEST
                          (
                          [Name] varchar(100),
                          ManagerName Varchar(100),
                          Number int
                          )



                          Insert into #TEST
                          Select x.[Name], x.ManagerName,x.number from (
                          select t.[Name],a.ManagerName as managerName, a.number as number from TEST t outer apply
                          (
                          select * from [fnRecursive](t.[Name],1)
                          ) a)
                          x

                          Select * from #Test


                          If we do a pivot on the table (excluding the 'Number' column). Assuming we store in the table "#temp" it should list all the managers as a column.



                           DECLARE @cols AS NVARCHAR(MAX),
                          @query AS NVARCHAR(MAX);

                          SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[ManagerName] )
                          FROM #temp c
                          FOR XML PATH(''), TYPE
                          ).value('.', 'NVARCHAR(MAX)')
                          ,1,1,'')



                          set @query = 'select * from #temp
                          pivot
                          (
                          min([managername])
                          for managername in (' + @cols + ')
                          ) p '

                          execute(@query)


                          But this doesn't name the column as 'Parent1', 'Parent2' instead with the dynamic column name.



                          Link below should help to set custom column name for the dynamic pivot table



                           https://stackoverflow.com/questions/16614994/sql-server-pivot-with-custom-column-names





                          share|improve this answer




























                            0












                            0








                            0







                            In order to get all parent or child, it's efficient to use a recursive function which would fetch the whole hierarchy.



                            Sample Table:



                            CREATE TABLE #TEST
                            (
                            [Name] varchar(100),
                            ManagerName Varchar(100),
                            Number int
                            )


                            Insert some values



                            Insert into Test values
                            ('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('f','g')


                            Create recursive function as below



                            CREATE FUNCTION [dbo].[fnRecursive] (@EmpName Varchar(100), @incremental int)
                            RETURNS @ret TABLE
                            (

                            ManagerName varchar(100),
                            Number int
                            )
                            AS
                            BEGIN
                            Declare @MgrName varchar(100)

                            SET @MgrName = (Select ManagerName from test where [name] = @EmpName)

                            Insert into @ret values (@MgrName, @incremental)
                            if(@MgrName is not null)
                            BEGIN
                            SET @incremental = @incremental + 1;
                            Insert into @ret
                            Select ManagerName, Number from [fnRecursive](@MgrName, @incremental)

                            END

                            RETURN;
                            END


                            If this function is joined with table, it should list the hierarchy for all employees



                            CREATE TABLE #TEST
                            (
                            [Name] varchar(100),
                            ManagerName Varchar(100),
                            Number int
                            )



                            Insert into #TEST
                            Select x.[Name], x.ManagerName,x.number from (
                            select t.[Name],a.ManagerName as managerName, a.number as number from TEST t outer apply
                            (
                            select * from [fnRecursive](t.[Name],1)
                            ) a)
                            x

                            Select * from #Test


                            If we do a pivot on the table (excluding the 'Number' column). Assuming we store in the table "#temp" it should list all the managers as a column.



                             DECLARE @cols AS NVARCHAR(MAX),
                            @query AS NVARCHAR(MAX);

                            SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[ManagerName] )
                            FROM #temp c
                            FOR XML PATH(''), TYPE
                            ).value('.', 'NVARCHAR(MAX)')
                            ,1,1,'')



                            set @query = 'select * from #temp
                            pivot
                            (
                            min([managername])
                            for managername in (' + @cols + ')
                            ) p '

                            execute(@query)


                            But this doesn't name the column as 'Parent1', 'Parent2' instead with the dynamic column name.



                            Link below should help to set custom column name for the dynamic pivot table



                             https://stackoverflow.com/questions/16614994/sql-server-pivot-with-custom-column-names





                            share|improve this answer















                            In order to get all parent or child, it's efficient to use a recursive function which would fetch the whole hierarchy.



                            Sample Table:



                            CREATE TABLE #TEST
                            (
                            [Name] varchar(100),
                            ManagerName Varchar(100),
                            Number int
                            )


                            Insert some values



                            Insert into Test values
                            ('a','b'), ('b','c'), ('c','d'), ('d','e'), ('e','f'), ('f','g')


                            Create recursive function as below



                            CREATE FUNCTION [dbo].[fnRecursive] (@EmpName Varchar(100), @incremental int)
                            RETURNS @ret TABLE
                            (

                            ManagerName varchar(100),
                            Number int
                            )
                            AS
                            BEGIN
                            Declare @MgrName varchar(100)

                            SET @MgrName = (Select ManagerName from test where [name] = @EmpName)

                            Insert into @ret values (@MgrName, @incremental)
                            if(@MgrName is not null)
                            BEGIN
                            SET @incremental = @incremental + 1;
                            Insert into @ret
                            Select ManagerName, Number from [fnRecursive](@MgrName, @incremental)

                            END

                            RETURN;
                            END


                            If this function is joined with table, it should list the hierarchy for all employees



                            CREATE TABLE #TEST
                            (
                            [Name] varchar(100),
                            ManagerName Varchar(100),
                            Number int
                            )



                            Insert into #TEST
                            Select x.[Name], x.ManagerName,x.number from (
                            select t.[Name],a.ManagerName as managerName, a.number as number from TEST t outer apply
                            (
                            select * from [fnRecursive](t.[Name],1)
                            ) a)
                            x

                            Select * from #Test


                            If we do a pivot on the table (excluding the 'Number' column). Assuming we store in the table "#temp" it should list all the managers as a column.



                             DECLARE @cols AS NVARCHAR(MAX),
                            @query AS NVARCHAR(MAX);

                            SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[ManagerName] )
                            FROM #temp c
                            FOR XML PATH(''), TYPE
                            ).value('.', 'NVARCHAR(MAX)')
                            ,1,1,'')



                            set @query = 'select * from #temp
                            pivot
                            (
                            min([managername])
                            for managername in (' + @cols + ')
                            ) p '

                            execute(@query)


                            But this doesn't name the column as 'Parent1', 'Parent2' instead with the dynamic column name.



                            Link below should help to set custom column name for the dynamic pivot table



                             https://stackoverflow.com/questions/16614994/sql-server-pivot-with-custom-column-names






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 23 '18 at 11:18

























                            answered Nov 22 '18 at 18:06









                            Prem KumarPrem Kumar

                            214




                            214






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53433788%2fsql-get-all-parents-childs%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Wiesbaden

                                Marschland

                                Dieringhausen