Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Database & SysAdmin
  3. Database
  4. How do hierarchy SELECT statement...

How do hierarchy SELECT statement...

Scheduled Pinned Locked Moved Database
tutorialdatabasequestion
9 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    RYU
    wrote on last edited by
    #1

    Hi, I have a table called tblUserDetail which contains the following attributes: - ID - ManagerID (which will refer to ID) - etc... Each user can have only 1 manager, but each user can have 0 or more staff. Now, I have the following structure

      A                        G
    

    ---|--- ---|---
    | | | | |
    B C D H I
    |
    E
    |
    F

    Therefore, if I choose person "A" (for example), it will allow me to add person "G" as person "A" staff. If I choose person "F" it will also allow me to add person "G" as person "F" staff. Now, I can handle 3 level of hierarchy, but I don't know how to do recursive in SQL statement. Here is my SQL Statement: eg. thisUserID = [current selected user] thisUserManagerID = [the selected manager id]

    strSQL = "SELECT UserID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE " +
    "UserID<>" + thisUserID.ToString() + " AND ManagerID<>" + thisUserID.ToString() + " AND " +
    "UserID<>" + thisUserManagerID.ToString() + " AND ManagerID=-1 AND " +
    "(NOT EXISTS(" +
    "SELECT * FROM tblUserDetail u2 WHERE u2.UserID=" + thisUserManagerID.ToString() + " AND " +
    "NOT EXISTS(" +
    "SELECT * FROM tblUserDetail u3 WHERE u1.UserID<>u2.ManagerID" +
    ")"
    +
    ")" +
    ")";

    Currently, if I choose person "F" it will allow me to add "A" and "G" as person "F" staff because it doesn't handle more than 3 level of hierarchy. Now, this works perfectly for 3 level of hierarchy, but I need more than 3 level. Is there a way to do recursive statement within SQL statement? Cheers :)

    S 1 Reply Last reply
    0
    • R RYU

      Hi, I have a table called tblUserDetail which contains the following attributes: - ID - ManagerID (which will refer to ID) - etc... Each user can have only 1 manager, but each user can have 0 or more staff. Now, I have the following structure

        A                        G
      

      ---|--- ---|---
      | | | | |
      B C D H I
      |
      E
      |
      F

      Therefore, if I choose person "A" (for example), it will allow me to add person "G" as person "A" staff. If I choose person "F" it will also allow me to add person "G" as person "F" staff. Now, I can handle 3 level of hierarchy, but I don't know how to do recursive in SQL statement. Here is my SQL Statement: eg. thisUserID = [current selected user] thisUserManagerID = [the selected manager id]

      strSQL = "SELECT UserID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE " +
      "UserID<>" + thisUserID.ToString() + " AND ManagerID<>" + thisUserID.ToString() + " AND " +
      "UserID<>" + thisUserManagerID.ToString() + " AND ManagerID=-1 AND " +
      "(NOT EXISTS(" +
      "SELECT * FROM tblUserDetail u2 WHERE u2.UserID=" + thisUserManagerID.ToString() + " AND " +
      "NOT EXISTS(" +
      "SELECT * FROM tblUserDetail u3 WHERE u1.UserID<>u2.ManagerID" +
      ")"
      +
      ")" +
      ")";

      Currently, if I choose person "F" it will allow me to add "A" and "G" as person "F" staff because it doesn't handle more than 3 level of hierarchy. Now, this works perfectly for 3 level of hierarchy, but I need more than 3 level. Is there a way to do recursive statement within SQL statement? Cheers :)

      S Offline
      S Offline
      Syed Mehroz Alam
      wrote on last edited by
      #2

      SQL Server 2005 provides common table expressions (CTE) for recursion. You can view more here[^] Regards, Mehroz

      R 1 Reply Last reply
      0
      • S Syed Mehroz Alam

        SQL Server 2005 provides common table expressions (CTE) for recursion. You can view more here[^] Regards, Mehroz

        R Offline
        R Offline
        RYU
        wrote on last edited by
        #3

        Hi Syed, I am having a trouble to bind between fields. Here is a simple example

        WITH NewUserDetail (UserID, ManagerID, FullName)
        AS
        (
        SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
        UNION ALL
        SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 WHERE u2.UserID<>u1.ManagerID
        )

        SELECT * FROM NewUserDetail

        And I got this message:

        Msg 4104, Level 16, State 1, Line 1
        The multi-part identifier "u1.ManagerID" could not be bound.

        I need to bind value to recursively go through all the users so the user will not be able to select its manager or manager of its manager. Any idea on how to tackle this problem? Cheers :)

        S 1 Reply Last reply
        0
        • R RYU

          Hi Syed, I am having a trouble to bind between fields. Here is a simple example

          WITH NewUserDetail (UserID, ManagerID, FullName)
          AS
          (
          SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
          UNION ALL
          SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 WHERE u2.UserID<>u1.ManagerID
          )

          SELECT * FROM NewUserDetail

          And I got this message:

          Msg 4104, Level 16, State 1, Line 1
          The multi-part identifier "u1.ManagerID" could not be bound.

          I need to bind value to recursively go through all the users so the user will not be able to select its manager or manager of its manager. Any idea on how to tackle this problem? Cheers :)

          S Offline
          S Offline
          Syed Mehroz Alam
          wrote on last edited by
          #4

          Seems you didnt get the cte syntax right. The second query inside the cte syntax generally joins with the cte itself, not the first query. Lets have a cte that lists your user and all its subordinates

          WITH NewUserDetail (UserID, ManagerID, FullName)
          AS
          (
          SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
          UNION ALL
          SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 WHERE u2.ManagerID=NewUserDetail.UserID
          )

          SELECT * FROM NewUserDetail

          K 1 Reply Last reply
          0
          • S Syed Mehroz Alam

            Seems you didnt get the cte syntax right. The second query inside the cte syntax generally joins with the cte itself, not the first query. Lets have a cte that lists your user and all its subordinates

            WITH NewUserDetail (UserID, ManagerID, FullName)
            AS
            (
            SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
            UNION ALL
            SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 WHERE u2.ManagerID=NewUserDetail.UserID
            )

            SELECT * FROM NewUserDetail

            K Offline
            K Offline
            Khawar Abbas1
            wrote on last edited by
            #5

            The problem resides in your recursive call. The line is "SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 WHERE u2.ManagerID=NewUserDetail.UserID" Here you have to add a inner join to the NewUserDetail table. I am also giving you an example. Hopefully it will solve your problem. The example is given below: WITH TemplateTopic(parent_id, child_id, child_name, child_type, Level)AS ( -- Anchor member definition SELECT a.parent_id,a.child_id, a.child_name, a.child_type, 0 AS Level FROM tbltemplate_topics a Where Child_Id = 16 UNION ALL ---- Recursive member definition SELECT a.parent_id,a.child_id, a.child_name, a.child_type, Level + 1 AS Level FROM tbltemplate_topics a INNER JOIN TemplateTopic AS d ON a.parent_id = d.child_id ) -- Statement that executes the CTE SELECT * FROM TemplateTopic (Make changes in your code accordingly)

            Do good and have good.

            S 1 Reply Last reply
            0
            • K Khawar Abbas1

              The problem resides in your recursive call. The line is "SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 WHERE u2.ManagerID=NewUserDetail.UserID" Here you have to add a inner join to the NewUserDetail table. I am also giving you an example. Hopefully it will solve your problem. The example is given below: WITH TemplateTopic(parent_id, child_id, child_name, child_type, Level)AS ( -- Anchor member definition SELECT a.parent_id,a.child_id, a.child_name, a.child_type, 0 AS Level FROM tbltemplate_topics a Where Child_Id = 16 UNION ALL ---- Recursive member definition SELECT a.parent_id,a.child_id, a.child_name, a.child_type, Level + 1 AS Level FROM tbltemplate_topics a INNER JOIN TemplateTopic AS d ON a.parent_id = d.child_id ) -- Statement that executes the CTE SELECT * FROM TemplateTopic (Make changes in your code accordingly)

              Do good and have good.

              S Offline
              S Offline
              Syed Mehroz Alam
              wrote on last edited by
              #6

              Oh...thanks for pointing. I missed the inner join part, dont know why.. Here is the modified cte

              WITH NewUserDetail (UserID, ManagerID, FullName)
              AS
              (
              SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
              UNION ALL
              SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 Inner Join NewUserDetail Manager WHERE u2.ManagerID=Manager.UserID
              )

              SELECT * FROM NewUserDetail

              R 1 Reply Last reply
              0
              • S Syed Mehroz Alam

                Oh...thanks for pointing. I missed the inner join part, dont know why.. Here is the modified cte

                WITH NewUserDetail (UserID, ManagerID, FullName)
                AS
                (
                SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
                UNION ALL
                SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u2 Inner Join NewUserDetail Manager WHERE u2.ManagerID=Manager.UserID
                )

                SELECT * FROM NewUserDetail

                R Offline
                R Offline
                RYU
                wrote on last edited by
                #7

                Hi Syed, I tried your example and it gave me this error

                Msg 156, Level 15, State 1, Line 6
                Incorrect syntax near the keyword 'WHERE'.

                Any idea? Thanks again :)

                R 1 Reply Last reply
                0
                • R RYU

                  Hi Syed, I tried your example and it gave me this error

                  Msg 156, Level 15, State 1, Line 6
                  Incorrect syntax near the keyword 'WHERE'.

                  Any idea? Thanks again :)

                  R Offline
                  R Offline
                  RYU
                  wrote on last edited by
                  #8

                  Hi Syed, Nevermind, I figured out the syntax with the help of the example given by Silent Eagle (thanks Silent Eagle). It should read:

                  WITH NewUserDetail (UserID, ManagerID, FullName)
                  AS
                  (
                  SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
                  UNION ALL
                  SELECT u2.UserID, u2.ManagerID, u2.FirstName + ' ' + u2.LastName As [FullName] FROM tblUserDetail u2 Inner Join NewUserDetail AS Manager ON u2.UserID<>Manager.ManagerID
                  )

                  But it again gave me another error on execution.

                  Msg 530, Level 16, State 1, Line 1
                  The statement terminated. The maximum recursion 100 has been exhausted before statement completion.

                  That is wierd because I did re-check and make sure there is no recursive employee-manager relation. Any idea? Thanks again :)

                  R 1 Reply Last reply
                  0
                  • R RYU

                    Hi Syed, Nevermind, I figured out the syntax with the help of the example given by Silent Eagle (thanks Silent Eagle). It should read:

                    WITH NewUserDetail (UserID, ManagerID, FullName)
                    AS
                    (
                    SELECT UserID, ManagerID, FirstName + ' ' + LastName As [FullName] FROM tblUserDetail u1 WHERE u1.UserID=12
                    UNION ALL
                    SELECT u2.UserID, u2.ManagerID, u2.FirstName + ' ' + u2.LastName As [FullName] FROM tblUserDetail u2 Inner Join NewUserDetail AS Manager ON u2.UserID<>Manager.ManagerID
                    )

                    But it again gave me another error on execution.

                    Msg 530, Level 16, State 1, Line 1
                    The statement terminated. The maximum recursion 100 has been exhausted before statement completion.

                    That is wierd because I did re-check and make sure there is no recursive employee-manager relation. Any idea? Thanks again :)

                    R Offline
                    R Offline
                    RYU
                    wrote on last edited by
                    #9

                    I see what is the problem. I shouldn't put

                    u2.UserID<>Manager.ManagerID

                    instead I should put

                    u2.UserID=Manager.ManagerID

                    Thanks Syed and Silent Eagle for your help. Cheers :)

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups