2009-07-17 15 views
5

Para esta pregunta, considere una aplicación que use una base de datos multitiende con modelado de fabricantes y modelos. Si hablamos de autos, entonces los fabricantes serían Ford, Chevrolet, BMW, etc. y los modelos serían F-150, Camaro y M3.Estructura de la base de datos maestros para datos maestros selectivamente anulada por cliente

La relación del modelo al fabricante es de una a una. Los datos para cada inquilino se separan usando un id_cliente.

Requisitos para el modelo de datos:

  • Los fabricantes y los modelos se puede definir a nivel de maestría para que estén disponibles para todos los clientes
  • al cliente seleccionar cuál de las entidades maestras que les gustaría usar
  • Los clientes pueden anular los atributos de un modelo maestro o fabricante
  • Los clientes pueden crear sus propios fabricantes
  • Los clientes pueden crear sus propios modelos para su propio fabricante o uno maestro
  • Otras entidades en el modelo estarán relacionadas con estas entidades por lo que es deseable que exista una tabla principal para cada una de las cuales se pueda crear una clave externa. Las tablas de fabricantes y modelos cumplen esa función en el ejemplo.

En este ejemplo:

  • cliente 1 utiliza Ford como está, anula Chevrolet, y añade dos fabricantes personalizados
  • cliente 1 utiliza Chevrolet y BMW como está y añade un fabricante de encargo
  • modelos se crean de acuerdo con los comentarios en el guión

continuación se muestra un ejemplo de implementación anotado que cumpla con todos los requi rements.

  • ¿Cómo se puede mejorar esto?
  • ¿De qué otras maneras podrían modelarse estas relaciones?

Tablas Fabricante

/* 
* Master manufacturers shared between all customers 
*/ 
CREATE TABLE master_manufacturers (
    master_manufacturer_id INTEGER NOT NULL, 
    name VARCHAR(100) NOT NULL, 
    attribute_1 VARCHAR(50), 
    /* ... */ 
    attribute_n VARCHAR(50), 
    PRIMARY KEY (master_manufacturer_id) 
); 

INSERT INTO 
    master_manufacturers (master_manufacturer_id, name) 
VALUES 
    (1, 'Ford'), 
    (2, 'Chevrolet'), 
    (3, 'BMW'); 

/* 
* A Customer's manufacturer. 
* If master_manufacturer_id IS NULL, then it is a custom manufacturer and manufacturer_custom contains the data 
* If master_manufacturer_id IS NOT NULL and manufacturer_custom does not exist, then the master is used without modification 
* If master_manufacturer_id IS NOT NULL and manufacturer_custom exists, then the master is overridden 
*/ 
CREATE TABLE manufacturers (
    manufacturer_id INTEGER NOT NULL, 
    customer_id INTEGER NOT NULL, 
    master_manufacturer_id INTEGER, 
    PRIMARY KEY (manufacturer_id), 
    FOREIGN KEY (master_manufacturer_id) REFERENCES master_manufacturers (master_manufacturer_id), 
    UNIQUE (customer_id, master_manufacturer_id) 
); 

INSERT INTO 
    manufacturers (manufacturer_id, customer_id, master_manufacturer_id) 
VALUES 
    (1, 1, 1), 
    (2, 1, 2), 
    (3, 1, NULL), 
    (4, 1, NULL), 
    (5, 2, 2), 
    (6, 2, 3),  
    (7, 2, NULL);  

CREATE TABLE manufacturer_custom (
    manufacturer_id INTEGER NOT NULL, 
    name VARCHAR(100) NOT NULL, 
    attribute_1 VARCHAR(50), 
    /* ... */ 
    attribute_n VARCHAR(50), 
    PRIMARY KEY (manufacturer_id), 
    FOREIGN KEY (manufacturer_id) REFERENCES manufacturers (manufacturer_id) 
); 

INSERT INTO 
    manufacturer_custom (manufacturer_id, name) 
VALUES 
    (2, 'Chevy'), 
    (3, 'Cust 1 Custom 1'), 
    (4, 'Cust 1 Custom 2'), 
    (7, 'Cust 2 Custom 1'); 

Tablas Modelo

/* 
* Master models shared between all customers 
*/ 
CREATE TABLE master_models (
    master_model_id INTEGER NOT NULL, 
    master_manufacturer_id INTEGER NOT NULL, 
    name VARCHAR(100) NOT NULL, 
    attribute_1 VARCHAR(50), 
    /* ... */ 
    attribute_n VARCHAR(50), 
    PRIMARY KEY (master_model_id), 
    FOREIGN KEY (master_manufacturer_id) REFERENCES master_manufacturers (master_manufacturer_id) 
); 

INSERT INTO 
    master_models (master_model_id, master_manufacturer_id, name) 
VALUES 
    (1, 1, 'F-150'), 
    (2, 1, 'F-250'), 
    (3, 1, 'Falcon'), 
    (4, 2, 'Camaro'), 
    (5, 2, 'Corvette'), 
    (6, 3, 'M3'), 
    (7, 3, '135i'); 

/* 
* A Customer''s model. 
* If master_model_id IS NULL, then it is a custom model and model_custom contains the data 
* If master_model_id IS NOT NULL and model_custom does not exist, then the master is used without modification 
* If master_model_id IS NOT NULL and model_custom exists, then the master is overridden 
*/ 
CREATE TABLE models (
    model_id INTEGER NOT NULL, 
    master_model_id INTEGER, 
    manufacturer_id INTEGER NOT NULL, 
    attribute_1 VARCHAR(50), 
    /* ... */ 
    attribute_n VARCHAR(50), 
    PRIMARY KEY (model_id), 
    FOREIGN KEY (master_model_id) REFERENCES master_models (master_model_id) 
); 

INSERT INTO 
    models (model_id, master_model_id, manufacturer_id) 
VALUES 
    (1, 1, 1), /* F-150 for customer_1's Ford */ 
    (2, 2, 1), /* F-250 for customer_1's Ford */ 
    (3, 4, 2), /* Camaro for customer_1's Chevy */ 
    (4, 4, 5), /* Camaro for customer_2's Chevrolet */ 
    (5, 5, 5), /* Corvette for customer_2's Chevrolet */ 
    (6, 6, 6), /* M3 for customer_2's BMW */ 
    (7, NULL, 1), /* F-350 (custom) for customer_1's Ford */ 
    (8, NULL, 6), /* M7 (custom) for customer_2's BMW */ 
    (9, NULL, 7); /* Custom Model (custom) for customer_2's Custom Mfg */ 

CREATE TABLE model_custom (
    model_id INTEGER NOT NULL, 
    name VARCHAR(100) NOT NULL, 
    attribute_1 VARCHAR(50), 
    /* ... */ 
    attribute_n VARCHAR(50), 
    PRIMARY KEY (model_id), 
    FOREIGN KEY (model_id) REFERENCES models (model_id) 
); 

INSERT INTO 
    model_custom (model_id, name) 
VALUES 
    (7, 'F-350'),  /* F-350 for customer_1's Ford */ 
    (8, 'M7'),   /* M7 for customer_2's BMW */ 
    (9, 'Custom Model'); /* Custom Model for customer_2's Custom Mfg */ 

Vistas para simplificar el uso de estas tablas

/* 
* View for a customer''s manufacturers 
*/ 
CREATE VIEW vw_manufacturers AS 
    SELECT 
     m.customer_id, 
     m.manufacturer_id, 
     COALESCE(cm.name, mm.name) AS name, 
     COALESCE(cm.attribute_1, mm.attribute_1) AS attribute_1, 
     /* ... */ 
     COALESCE(cm.attribute_n, mm.attribute_n) AS attribute_n 
    FROM 
     manufacturers m 
    LEFT JOIN 
     master_manufacturers mm 
    USING 
     (master_manufacturer_id) 
    LEFT JOIN 
     manufacturer_custom cm 
    USING 
     (manufacturer_id); 

/* 
* View for a customer's models 
*/ 
CREATE VIEW vw_models AS 
    SELECT 
     mfg.customer_id, 
     mfg.manufacturer_id, 
     mfg.name AS manufacturers_name, 
     m.model_id, 
     COALESCE(cm.name, mm.name) AS name, 
     COALESCE(cm.attribute_1, mm.attribute_1) AS attribute_1, 
     /* ... */ 
     COALESCE(cm.attribute_n, mm.attribute_n) AS attribute_n 
    FROM 
     vw_manufacturers mfg, 
     models m 
    LEFT JOIN 
     master_models mm 
    USING 
     (master_model_id) 
    LEFT JOIN 
     model_custom cm 
    USING 
     (model_id) 
    WHERE 
     mfg.manufacturer_id = m.manufacturer_id; 

Fabricantes para customer_id 1

SELECT manufacturer_id, name FROM vw_manufacturers WHERE customer_id = 1;

manufacturer_id |  name  
-----------------+----------------- 
      1 | Ford 
      2 | Chevy 
      3 | Cust 1 Custom 1 
      4 | Cust 1 Custom 2 

Fabricantes para customer_id 2

SELECT manufacturer_id, name FROM vw_manufacturers WHERE customer_id = 2;

manufacturer_id |  name  
-----------------+----------------- 
      5 | Chevrolet 
      6 | BMW 
      7 | Cust 2 Custom 1 

Modelos para customer_id 1

SELECT * FROM vw_models WHERE customer_id = 1;

customer_id | manufacturer_id | manufacturers_name | model_id | name 
-------------+-----------------+--------------------+----------+-------- 
     1 |    1 | Ford    |  1 | F-150 
     1 |    1 | Ford    |  2 | F-250 
     1 |    2 | Chevy    |  3 | Camaro 
     1 |    1 | Ford    |  7 | F-350 

Modelos para customer_id 2

SELECT * FROM vw_models WHERE customer_id = 2;

customer_id | manufacturer_id | manufacturers_name | model_id |  name  
-------------+-----------------+--------------------+----------+-------------- 
      2 |    5 | Chevrolet   |  4 | Camaro 
      2 |    5 | Chevrolet   |  5 | Corvette 
      2 |    6 | BMW    |  6 | M3 
      2 |    6 | BMW    |  8 | M7 
      2 |    7 | Cust 2 Custom 1 |  9 | Custom Model 

Respuesta

2

Se necesitan las siguientes tablas:

  • FABRICANTE-CODE
  • FABRICANTES DE TIPO-CODE
  • FABRICANTE-DETALLES
  • MODELO-CODE
  • MODELOS DE TIPO-CODE
  • MODELO-DETALLES

Si tiene tablas con datos idénticos: debe consolidarlos y utilizar una tabla TYPE_CODE para diferenciarlos.

Re: FABRICANTES & CLIENTES Actualmente, necesita que el PK sea FABRICANTE-ID y CLIENTE-ID. Mejor dividir FABRICANTES en FABRICANTES-CÓDIGO y FABRICANTES-DETALLES. FABRICANTE-CÓDIGO contendría "BMW", "FORD", etc. más personalizado. FABRICANTES-DETALLES le permitiría mantener los detalles de los datos por cliente, al mismo tiempo que le permite reutilizar códigos para cosas como "BMW"/etc. Lo mismo ocurre con los modelos.

El siguiente paso sería definir tablas de CÓDIGO TIPO para cosas como motor, ruedas, etc. Relacionaré esto con los DETALLES DEL MODELO usando una tabla XREF llamada MODELO-ATRIBUTOS.El modelo de atributos de tabla contendría:

  • MODELO-DETALLES-ID (pk)
  • modelo de atributo tipo-CODE (pk)
  • ATTRIBUTE-CODE (pk)

Esto permitiría asociar atributos de modelo opcionales con el registro MODELO-DETALLES aplicable, sin agregar constantemente atributos a la tabla MODELO-DETALLES.

FABRICANTE-CODE

  • FABRICANTE-CODE VARCHAR (4) (pk)
  • DESCRIPCIÓN
  • EFICAZ-FECHA no nulo
  • fecha de expiración no nulo

CÓDIGO DE FABRICANTE | DESCRIPCIÓN | FECHA DE VIGENCIA | FECHA DE VENCIMIENTO
FORD | FORD | 01-01-1900 | 12-31-9999
BMW | BMW | 01-01-1900 | 12-31-9999
CHEV | Chevrolet | 01-01-1900 | 12-31-9999

FABRICANTE DE TIPO-CODE

  • FABRICANTE DE TIPO-CODE (pk)
  • descripción no nula

FABRICANTE DE TIPO-CODE | DESCRIPCIÓN
MASTER | Maestro
PERSONALIZADO | Custom

FABRICANTE-DETALLES

  • FABRICANTE-DETALLES-ID (pk)
  • FABRICANTE-CODE (fk) no nulo
  • FABRICANTE-TYPE-CODE (fk) no nulo
  • id-cliente (FK) no es nulo

FABRICANTE-DATOS-ID | CÓDIGO DE FABRICANTE | CÓDIGO DE TIPO FABRICANTE | ID de cliente
1 | BMW | MASTER | 1
2 | BMW | PERSONALIZADO | 1

MODELO

  • MODELO-ID (pk)
  • FABRICANTE-DETALLES-ID (fk) no nulo
  • descripción no nulo

MODELO-ID | FABRICANTE-DETALLES-ID | DESCRIPCIÓN
1 | 1 | M3
1 | 2 | M3 bajó

+0

¿Puede aclarar cómo funcionaría esto? No lo entiendo del todo. Un ejemplo completo de la estructura para los fabricantes sería genial. Tratando de resolverlo obtengo lo siguiente, pero no creo que sea de lo que estás hablando. FABRICANTE-CODE (mfg_id (PK), código) FABRICANTE-DETALLES (mfg_id, (FK, PK), customer_id (PK), attr1, attr) FABRICANTES-TYPE-CODE (mfg_id (FK, PK) , is_master) – cope360

+0

¿Cómo funciona customer_id como columna no nula de FABRICANTES-DETALLES? En el ejemplo, lo tiene configurado en 1 para un tipo MASTER, pero los tipos MASTER deben estar disponibles para todos los clientes. – cope360

+0

No nulo significa que la columna no puede tener nulos, lo que significa que en este caso no podría tener un registro en DETALLES DEL FABRICANTE sin una IDENTIFICACIÓN DEL CLIENTE asociada. El valor MASTER es una clave externa (de ahí la abreviatura fk) de la tabla CÓDIGO DE TIPO DE FABRICANTE: es una clave natural, no usa un número para identificarla. Dicho esto, no hay límite en el modelo de datos actual para limitar qué clientes ver qué tipo de CÓDIGO DE FABRICANTE registra. Si quisiera esto, necesitaría agregar una tabla entre MANUFACTURER-TYPE-CODE y CUSTOMER usando un combo de pk de cualquier tabla como pk. –

-2

Depende del uso de este sistema. Debería diseñar esto de manera diferente para OLAP frente a OLTP.

En teoría, todo esto podría estar en 1 tabla ....

Cuestiones relacionadas