2010-03-19 15 views
6

NotaSQL Server 2005 de diseño de base de datos - muchos-a-muchos relación con la jerarquía

He reescrito por completo mi post original para explicar mejor el tema que estoy tratando de entender. He tratado de generalizar el problema tanto como sea posible.

Además, mi agradecimiento a las personas originales que respondieron. Esperemos que este mensaje aclare un poco las cosas.

Contexto

En resumen, estoy luchando para entender la mejor manera de diseñar una base de datos a pequeña escala para manejar (lo que percibo como) múltiples relaciones de muchos a muchos.

imaginar el siguiente escenario para una estructura organizativa de la empresa:

   Textile Division     Marketing Division 
        |          | 
      ----------------------    ---------------------- 
      |     |    |     | 
     HR Dept   Finance Dept  HR Dept   Finance Dept 
      |     |    |     | 
     ----------   ----------  ----------   --------- 
    |   |   |  |  |  |   |  | 
    Payroll  Hiring Audit  Tax Payroll Hiring  Audit Accounts 
    |   |   |  |  |  |   |  | 
    Emps  Emps  Emps  Emps Emps  Emps  Emps Emps  

NB: Emps denota una lista de employess que trabajan en esa área

Cuando empecé con este tema que hice cuatro tablas separadas :

  1. Divisions -> Textil, marketing (PK = DivisionID)
  2. Departments -> recursos humanos, Finanzas (PK = DeptID)
  3. Functions -> nómina, contratación, auditoría, impuestos, cuentas (PK = FunctionID)
  4. Employees -> Lista de todos los empleados (PK = EmployeeID)

El problema, como yo lo veo, es que existen múltiples relaciones de muchos a muchos, es decir, muchos departamentos tienen muchas divisiones y muchas funciones tienen muchos departamentos.

Pregunta

dando a la estructura de base de datos anterior, supongamos que se quiere hacer lo siguiente:

  • Obtener todos los empleados que trabajan en la función de nómina de la División de Marketing

Para hacer esto, necesito poder diferenciar entre los dos departamentos de nómina pero no estoy seguro de cómo se puede hacer esto.

Entiendo que podría construir una tabla 'Enlace/Cruce' entre Departamentos y Funciones para que pueda recuperar qué Funciones están en qué Departamentos. Sin embargo, aún necesitaría diferenciar la División a la que pertenecen.

esfuerzo de investigación

Como se puede ver que soy un principiante cuando se trata de deisgn base de datos. He pasado los últimos dos días rescatando este problema, atravesando modelos de conjuntos anidados, modelos de adyacencia, leyendo que este problema se sabe que no es NP completo, etc. Estoy seguro de que hay una solución simple.

+0

sí, tiene una solución, no se preocupe.los conjuntos anidados podrían hacerlo (pero podría ser una exageración). ¿podría definir si desea trabajar con jerarquías generales de cualquier nivel o sabe que tendrá una jerarquía de 3 niveles? – Unreason

+0

@Goran: por el momento solo será una jerarquía de 3 niveles. –

+0

bien, entonces por el momento mi respuesta sigue en pie. :) – Unreason

Respuesta

2

Basado en la publicación actualizada, y haciendo algunas suposiciones (bastante obvias) basadas en los nombres utilizados, se me ocurre lo siguiente.Hay cuatro entidades:

  • Divisiones
  • Departamentos
  • Funciones
  • Entidades

Hay muchas relaciones entre estas entidades. Pocos de ellos son jerárquicos, la mayoría son asociaciones simples:

  • Opción A1: hay una lista maestra de funciones. Cada departamento puede realizar (o hacer) una o más funciones, y una función puede ser realizada por más que en el departamento.
  • Opción A2: las funciones son "propiedad" de los departamentos. Ninguna función puede ser realizada por dos o más departamentos. (Este parece ser el caso, ya que el Departamento de RRHH tiene Nómina y Contratación, y el Departamento de Finanzas tiene Auditoría, Impuestos y Cuentas).

  • Las funciones son realizadas por departamentos para (en nombre de) divisiones. (HR Dept tiene Nómina y Contratación para las divisiones de Textil y Marketing; Departamento de Finanzas hace Auditoría e Impuestos - pero no Cuentas - para la división Textil, y Auditoría y Cuentas - pero no Impuestos - para la división de Marketing.) Tal vez un poco más precisamente, los departamentos realizan funciones seleccionadas para las divisiones seleccionadas a las que están asociadas, y esa asociación se define por el rendimiento de esa función.

  • Más allá de realizar el trabajo de las funciones, no parece haber relación entre departamentos y divisiones. No existe una relación jerárquica entre ellos, ya que uno no "posee" ni contiene el otro.

Esto conduce a éstos se delimitaron las tablas:

-- Division ----- 
DivisionId (primary key) 

-- Department --- 
DepartmentId (primary key) 

-- Function ----- (assumes option A2) 
FunctionId (primary key) 
DepartmentId (foreign key, references Department) 

-- DivisionFunctions ---- 
DivisionId (First column of compound primary key) 
FunctionId (Second column of compound primary key) 

(Usted podría incluir opcionalmente una clave sustituta para identificar de forma única cada fila, pero DivisionId + FunctionId funcionaría.)

Hay no hay suficiente material aquí para completamente describir cómo los "empleados" se ajustan al modelo. Dado que los empleados hacen el trabajo de las funciones: ¿puede un empleado hacer el trabajo de más de una función, o solo hacen una? ¿Un empleado hace el trabajo de la función independientemente de la (s) división (es) para la que se está haciendo, o están asignados para hacer el trabajo para una o más divisiones? Dos opciones obvias aquí, aunque más complejo variantes son posibles:

  • Opción B1: Los empleados hacen el trabajo de una o más funciones dentro de los departamentos, y llevar a cabo ese trabajo para todas las divisiones que requieren que la función de ese departamento.
  • Opción B2: los empleados están asignados para realizar una función específica para una división específica.

Teniendo en cuenta estos, mesas podrían ser:

-- Employee ----- (assumes option B1) 
EmployeeId (primary key) 
DepartmentId (foreign key, references Department) 

-- EmployeeFunction ----- (assumes option B1) 
EmployeeId (First column of compound primary key) 
FunctionId (Second column of compound primary key) 

... y por lo tanto todos los empleados que pueden realizar una función se llevará a cabo para todas las divisiones que lo requieran.O,

-- Employee ----- (assumes option B2) 
EmployeeId (primary key) 
DepartmentId (foreign key, references Department) 

-- EmployeeAssignment ----- (assumes option B2) 
EmployeeId (foreign key, references Employee) 
DivisionId (first of two-column foreign key referencing DivisionFunctions) 
FunctionId (second of two-column foreign key referencing DivisionFunctions) 

(o, en lugar de DivisionId y FunctionId, incluya la clave sustituta opcional desde DivisionFunctions.) ... y por lo tanto los empleados están asignados de forma individual a las funciones a realizar por el departamento para una división.

Pero eso aún deja muchas preguntas de "qué pasaría si/cuándo": ¿los empleados "pertenecen" a los departamentos? ¿Pueden los empleados pertenecer (trabajar para) múltiples departamentos? ¿Quizás los empleados pertenecen a divisiones? ¿Realiza un seguimiento de las funciones que puede realizar un empleado, incluso si actualmente no lo hace? De manera similar, ¿realiza un seguimiento del departamento para el que trabaja un empleado, incluso si actualmente se encuentran "entre funciones"? Si un empleado puede realizar las funciones A y B, y una división requiere ambas funciones, ¿se le puede asignar a un empleado que solo realice A y no B para esa división?

Hay más investigación de requisitos que hacer aquí, pero me gustaría pensar que este es un buen comienzo.

+0

Philip - Respuesta excelente y completa. Creo que realmente podría usar esto para aumentar mi pensamiento y mi enfoque. Lo digeriré en las próximas 24 horas. Nota rápida: los empleados solo pueden trabajar para una función. No pueden trabajar para múltiples funciones o divisiones. –

1

Bueno, no lo pondría todo en una sola mesa. Necesita leer sobre la normalización de datos y uniones. (Y nunca almacene nada en una lista delimitada por comas.)

Ninguna base de datos que valga la pena tendría el menor problema al manejar un millón de registros, es decir, una base de datos minúscula.

Necesita tablas para funciones, cursos, ubicaciones, personas, organización y posiblemente algunas tablas de unión para acomodar de muchas a muchas relaciones. Pero nada de esto es difícil o incluso más allá de un diseño muy básico. Recomiendo que antes de hacer cualquier cosa, obtenga un libro en la base de datos elegida y lea lo básico.

+1

+1 para la última sesión, recomendando algunos libros de diseño de DB. –

+0

HLGEM - He editado mi publicación original para aclarar un poco las cosas, ya que creo que de entrada me he confundido. Por cierto, ordenó 'SQL para Smarties' por Celko. Estoy usando SQL Server 2005, ¿algún libro que recomiendas? –

+0

Nos saltamos 2005, así que no tengo este libro, pero parece que tiene lo que necesita http://www.amazon.com/Server-2005-Database-Design-Optimization/dp/1590595297/ref= sr_1_1? ie = UTF8 & s = books & qid = 1269020643 & sr = 1-1 # noop – HLGEM

0

Trate de darle a cada entidad una mesa de su propio ejemplo

//Table Structure 
location 
    locationId 
    name 

division 
    divisionId 
    name 
    locationId (fk => location) 

department 
    deparmentId 
    name 
    divisionId (fk => division) 

function 
    functionId 
    name 
    departmentId(fk => department) 

jobrole 
    jobroleId 
    name 
    functionId 

course 
    courseID 
    name 

jobrole_course_requirement 
    jobroleID 
    courseID 

employee 
    employeeID 
    name 

employee_jobRole 
    employeeID 
    jobRoleId 

emploeyee_course_attendance 
    emploeyee_course_attendanceID 
    emploeyeeID 
    courseID 
    dateAttended 

Y la parte de la muestra selecciona

// Get course requirements for an employee 
select course.name 
    from course, 
     jobrole_course_requirement, 
     employee_jobRole 
    where 
     employee_jobRole.employeeID = 123 and 
     jobrole_course_requirement.JobRoleId = employee_jobRole.JobRoleId 
     course.courseID = jobrole_course_requirement.courseID 
+0

David - He editado mi publicación original para aclarar un poco las cosas, ya que creo que de entrada me he confundido. –

0

lo general, cuando soy la creación de una base de datos, que llegar a lo que las entidades que necesito y cómo se relacionan entre sí (es decir, muchos-uno, uno-uno, ...). Lo cual parece que has hecho. Entonces, después, averiguo qué necesitará cada entidad. Por ejemplo, Location puede tener: locationid, address, ... Then, Divisions Asumiendo que cada una de ellas tiene una ubicación para muchas divisiones, puede hacer que la entidad de división tenga una divisionid, locationid, la información que necesita cada división. Entonces, básicamente, si se trata de una relación uno-muchos como una ubicación para muchas divisiones, podría simplemente poner la identificación de la ubicación en la tabla de división. Sin embargo, si se trata de una relación de muchos y muchos, probablemente sea mejor tener una tabla intermedia para conectar los dos, por lo que no es necesario tener registros duplicados con solo un cambio de id.

+0

John - He editado mi publicación original para aclarar un poco las cosas, ya que creo que inicialmente me confundí. –

1

Necesita una relación simple con una relación. La Posición (tabla de hechos) tiene solo ID's de tablas maestras relacionadas (Departamento, División etc.). Esto permite cualquier combinación de las tablas maestras que se utilizarán

Las tablas maestras pueden tener una jerarquía simple integrada en cada una de ellas según sea necesario. Y pueden relacionarse entre sí según sea necesario. Pero el detalle de esta no afecta a las consultas en Posición

Puede hacer identificaciones en Posición anulable para las relaciones opcionales

Se podría añadir un StartDate y EndDate columnas a Posición para seguir los cambios más tiempo

Un ejemplo sencillo de esto es:

SQL Table Diagram http://img52.imageshack.us/img52/3484/sqldiag1.jpg

+0

Creo que su solución no está completamente normalizada, por ejemplo, Finanzas en Marketing no tiene impuestos y Finanzas en Textil no tiene cuentas. Eso es algo que su modelo no puede reflejar. Su solución se normaliza solo si no hay dependencias funcionales entre DepartmentID, FunctionID, EmployeeID (si son independientes) – Unreason

+0

corrección: se suponía que era DepartmentID, FunctionID y DivisionID – Unreason

+0

Duh! Es una muestra para mostrar las posibilidades. Puede agregar dependencias según sea necesario (ejemplo mostrado para departamento y división). No tenemos suficiente información para hacerlo * normalizado *, @Remnant solo puede agregar una relación de departamento a función, etc. – TFD

0

Quizás (probablemente) deba considerar el departamento de Recursos Humanos de la división de Textiles como un departamento diferente al departamento de Recursos Humanos de la división de Marketing.

1

Como es de "abc" :), una cosa que hacer antes de cualquier intento para sentirse como en casa con el diseño de base de datos se lee acerca de la normalización, y para entender completamente todas las formas normales hasta 5NF

Si desea modelo que
1. departamentos están en divisiones
2. las funciones se llevan a cabo en los departamentos
3. los empleados realizan funciones

y que no todas las funciones se realizan en todos los departamentos, ni todos los departamentos están en todo divisiones th es que tienes que guardar ese hecho en alguna parte.

Mientras se hace el diseño lógico, y comparte sus mesas nombres descriptivos, por lo que algunos departamentos se encuentran en las divisiones

departments_in_divisions 
candidate key: department, division 

entonces usted tiene algunas funciones en algunos departamentos

functions_departments_divisions 
candidate key: function, department, division 
references: (department, division) in departments_divisions 

entonces los empleados tienen algunas funciones de algunos departamentos y divisiones

employees_function_department_division 
candidate key: employee, function, department, division 
references: (function, department, division) in functions_departments_divisions 

Afte r (o antes de esto) tiene 3 entidades más, funciones, departamentos y divisiones que enumerarían todos los posibles departamentos, divisiones y funciones a los que también se haría referencia en las tablas anteriores (esto podría no estar completamente normalizado).

También los nombres de las entidades (tablas) pueden convertirse en algo más apropiado para usted (solo usted puede conocer la semántica completa del modelo de sus datos). Especialmente si observa que necesita asignarles otros atributos (campos).

Los valores de los departamentos, divisiones y funciones son sus nombres, no existen identificadores artificiales aún en el análisis anterior. Puede presentarlos en el siguiente paso, después de que el modelado lógico se base en el modelado físico, o puede conservar las claves naturales. Si usa claves artificiales que pueden reducir el uso de claves compuestas hasta un máximo de 2, pero confunde las relaciones y el significado de los hechos que está almacenando en sus tablas. (Ejemplo: ID de función puede ser ID de un nombre de función o ID de una función que se realiza en cierta combinación de división/departamento; no está claro qué es y estos no son intercambiables, más o menos como la diferencia entre una instancia y una clase).

Cuestiones relacionadas