locked
Database design RRS feed

  • Question

  • Suppose I have employees and departments where one employee can belong to different department with different role.

    For example Emp 1 belongs to Dept 1 with role manager. where the same employee can belong to Dept 2 with role service man .

    Each employee also have child hierarchy like Emp 2, Emp 3 belongs to Dept 1 with role assistant and their parent is Emp 1.

    In this case what will be the best solution for designing this concept. Please share your opinion.

    Friday, July 24, 2020 8:12 AM

All replies

  • Hi,

    Hope the following samples can help you.

    SQL HR Sample Database 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, July 24, 2020 9:13 AM
  • Hi friend,

    Is there any update on this case?
    Please feel free to drop us a note if there is any update.

    Best Regards,
    Cris


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, July 27, 2020 1:00 AM
  • >>Each employee also have child hierarchy like Emp 2, Emp 3 belongs to Dept 1 with role assistant and their parent >>is Emp 1.

    Itzik Ben-Gan has great examples , please see below

    CREATE TABLE Employees
    (
      empid   int         NOT NULL,
      mgrid   int         NULL,
      empname varchar(25) NOT NULL,
      salary  money       NOT NULL,
      CONSTRAINT PK_Employees PRIMARY KEY(empid),
      CONSTRAINT FK_Employees_mgrid_empid
        FOREIGN KEY(mgrid)
        REFERENCES Employees(empid)
    )
    CREATE INDEX idx_nci_mgrid ON Employees(mgrid)
    SET NOCOUNT ON
    INSERT INTO Employees VALUES(1 , NULL, 'Nancy'   , $10000.00)
    INSERT INTO Employees VALUES(2 , 1   , 'Andrew'  , $5000.00)
    INSERT INTO Employees VALUES(3 , 1   , 'Janet'   , $5000.00)
    INSERT INTO Employees VALUES(4 , 1   , 'Margaret', $5000.00) 
    INSERT INTO Employees VALUES(5 , 2   , 'Steven'  , $2500.00)
    INSERT INTO Employees VALUES(6 , 2   , 'Michael' , $2500.00)
    INSERT INTO Employees VALUES(7 , 3   , 'Robert'  , $2500.00)
    INSERT INTO Employees VALUES(8 , 3   , 'Laura'   , $2500.00)
    INSERT INTO Employees VALUES(9 , 3   , 'Ann'     , $2500.00)
    INSERT INTO Employees VALUES(10, 4   , 'Ina'     , $2500.00)
    INSERT INTO Employees VALUES(11, 7   , 'David'   , $2000.00)
    INSERT INTO Employees VALUES(12, 7   , 'Ron'     , $2000.00)
    INSERT INTO Employees VALUES(13, 7   , 'Dan'     , $2000.00)
    INSERT INTO Employees VALUES(14, 11  , 'James'   , $1500.00)

    -----------------------------
    The first request is probably the most common one:
     returning an employee (for example, Robert whose empid=7) 
    and his/her subordinates in all levels. 
    The following CTE provides a solution to this request:

    WITH EmpCTE(empid, empname, mgrid, lvl)
    AS


      -- Anchor Member (AM)
      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = 7
      UNION ALL
      
      -- Recursive Member (RM)
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees AS E
        JOIN EmpCTE AS M
          ON E.mgrid = M.empid
    )
    SELECT * FROM EmpCTE
    --------------------------------------
    Using this level counter you can limit the number of iterations
     in the recursion. For example, the following CTE is used to return 
    all employees who are two levels below Janet:

    WITH EmpCTEJanet(empid, empname, mgrid, lvl)
    AS

      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = 3
      UNION ALL
      
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees as E
        JOIN EmpCTEJanet as M
          ON E.mgrid = M.empid
      WHERE lvl < 2
    )
    SELECT empid, empname
    FROM EmpCTEJanet
    WHERE lvl = 2

    ------------------------------------------
    As mentioned earlier, CTEs can refer to
     local variables that are defined within the same batch.
     For example, to make the query more generic, you can use 
    variables instead of constants for employee ID and level:

    DECLARE @empid AS INT, @lvl AS INT
    SET @empid = 3 -- Janet
    SET @lvl   = 2 -- two levels
    WITH EmpCTE(empid, empname, mgrid, lvl)
    AS

      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = @empid
      UNION ALL
      
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees as E
        JOIN EmpCTE as M
          ON E.mgrid = M.empid
      WHERE lvl < @lvl
    )
    SELECT empid, empname
    FROM EmpCTE
    WHERE lvl = @lvl
    -----------------------------------------------
    Results generated thus far might be returned (but are not guaranteed to be), 
    and error 530 is generated. You might think of using the MAXRECURSION option 
    to implement the request to return employees who are two levels below 
    Janet using the MAXRECURSION hint instead of the filter in the recursive member

    WITH EmpCTE(empid, empname, mgrid, lvl)
    AS

      SELECT empid, empname, mgrid, 0
      FROM Employees
      WHERE empid = 1
      UNION ALL

      SELECT E.empid, E.empname, E.mgrid, M.lvl+1
      FROM Employees as E
        JOIN EmpCTE as M
          ON E.mgrid = M.empid
    )
    SELECT * FROM EmpCTE
    OPTION (MAXRECURSION 2)
    ------------------------------------------------

    WITH EmpCTE(empid, empname, mgrid, lvl, sortcol)
    AS

      SELECT empid, empname, mgrid, 0,
        CAST(empid AS VARBINARY(900))
      FROM Employees
      WHERE empid = 1
      UNION ALL
      SELECT E.empid, E.empname, E.mgrid, M.lvl+1,
        CAST(sortcol + CAST(E.empid AS BINARY(4)) AS VARBINARY(900))
      FROM Employees AS E
        JOIN EmpCTE AS M
          ON E.mgrid = M.empid
    )
    SELECT
      REPLICATE(' | ', lvl)
        + '(' + (CAST(empid AS VARCHAR(10))) + ') '
        + empname AS empname
    FROM EmpCTE
    ORDER BY sortcol
    (1) Nancy
     | (2) Andrew
     |  | (5) Steven
     |  | (6) Michael
     | (3) Janet
     |  | (7) Robert
     |  |  | (11) David
     |  |  |  | (14) James
     |  |  | (12) Ron
     |  |  | (13) Dan
     |  | (8) Laura
     |  | (9) Ann

     | (4) Margaret
     |  | (10) Ina
    -------------------------------


    Best Regards,Uri Dimant SQL Server MVP, http://sqlblog.com/blogs/uri_dimant/

    MS SQL optimization: MS SQL Development and Optimization
    MS SQL Consulting: Large scale of database and data cleansing
    Remote DBA Services: Improves MS SQL Database Performance
    SQL Server Integration Services: Business Intelligence

    • Proposed as answer by Naomi NEditor Monday, July 27, 2020 4:10 AM
    Monday, July 27, 2020 3:57 AM