6

この質問では、メーカーとモデルのモデリングを備えたマルチテナントデータベースを使用するアプリケーションについて考えてみます。車の話をすると、メーカーはフォード、シボレー、BMWなどで、モデルはF-150、カマロ、M3になります。

モデルとメーカーの関係は多対1です。各テナントのデータは、customer_idを使用して分離されます。

データモデルの要件:

  • メーカーとモデルをマスターレベルで定義して、すべての顧客が利用できるようにすることができます
  • お客様は、使用するマスターエンティティを選択します
  • 顧客はマスターモデルまたはメーカーの属性を上書きできます
  • 顧客は独自のメーカーを作成できます
  • お客様は、自社またはマスターメーカー向けに独自のモデルを作成できます
  • モデル内の他のエンティティはこれらのエンティティに関連しているため、外部キーを作成できるメインテーブルがそれぞれに1つあることが望ましいです。この例では、メーカーとモデルのテーブルがその役割を果たします。

この例では:

  • 顧客1は、フォードを現状のまま使用し、シボレーをオーバーライドし、2つのカスタムメーカーを追加します
  • 顧客1はシボレーとBMWをそのまま使用し、1つのカスタムメーカーを追加します
  • スクリプトのコメントに従ってモデルが作成されます

以下は、すべての要件を満たす注釈付きのサンプル実装です。

  • これをどのように改善できますか?
  • これらの関係を他にどのようにモデル化できますか?

メーカーテーブル

/*
 * 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');

モデルテーブル

/*
 * 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 */

これらのテーブルの使用を簡素化するビュー

/*
 * 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;

customer_id1のメーカー

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

customer_id2のメーカー

SELECT manufacturer_id, name FROM vw_manufacturers WHERE customer_id = 2;

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

customer_id1のモデル

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

customer_id2のモデル

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
4

2 に答える 2

2

次のテーブルが必要です。

  • 製造元コード
  • 製造元-タイプコード
  • 製造元-詳細
  • モデルコード
  • モデル-タイプコード
  • モデル-詳細

同一のデータを持つテーブルがある場合は、それらを統合し、TYPE_CODEテーブルを使用してそれらを区別する必要があります。

Re:MANUFACTURERS&CUSTOMERS現在、PKはMANUFACTURER-IDとCUSTOMER-IDである必要があります。MANUFACTURERSをMANUFACTURERS-CODEとMANUFACTURER-DETAILSに分割することをお勧めします。MANUFACTURER-CODEには、「BMW」、「FORD」などに加えてカスタムが含まれます。MANUFACTURER-DETAILSを使用すると、顧客ごとに詳細データを保持しながら、「BMW」などのコードを再利用できます。モデルについても同じことが言えます。

次のステップは、エンジン、ホイールなどのTYPE-CODEテーブルを定義することです。MODEL-ATTRIBUTESと呼ばれるXREFテーブルを使用して、これらをMODEL-DETAILSに関連付けます。MODEL-ATTRIBUTESテーブルには次のものが含まれます。

  • モデル-詳細-ID(pk)
  • モデル-属性-タイプコード(pk)
  • 属性コード(pk)

これにより、MODEL-DETAILSテーブルに属性を絶えず追加することなく、オプションのモデル属性を該当するMODEL-DETAILSレコードに関連付けることができます。

製造元コード

  • MANUFACTURER-CODE VARCHAR(4)(pk)
  • 説明
  • EFFECTIVE-DATEはnullではありません
  • EXPIRY-DATEはnullではありません

製造元コード| 説明| 発効日| 有効期限
フォード| フォード| 01-01-1900 | 12-31-9999
BMW | BMW | 01-01-1900 | 12-31-9999
CHEV | シボレー| 01-01-1900 | 12-31-9999

製造元-タイプコード

  • 製造元-タイプコード(pk)
  • 説明はnullではありません

MANUFACTURER-TYPE-CODE | 説明
マスター| マスター
カスタム| カスタム

製造元-詳細

  • 製造元-詳細-ID(pk)
  • MANUFACTURER-CODE(fk)not null
  • MANUFACTURER-TYPE-CODE(fk)not null
  • CUSTOMER-ID(fk)はnullではありません

製造元-詳細-ID| 製造元コード| MANUFACTURER-TYPE-CODE | 顧客ID1
| BMW | マスター| 1
2 | BMW | カスタム| 1

モデル

  • モデルID(pk)
  • MANUFACTURER-DETAILS-ID(fk)not null
  • 説明はnullではありません

モデルID| 製造元-詳細-ID| 説明
1| 1 | M3
1 | 2 | M3が下がった

于 2009-07-18T05:23:39.193 に答える
-3

それはこのシステムの使用に依存します。これは、OLAPとOLTPで異なる方法で設計します。

理論的には、これはすべて1つのテーブルに含まれる可能性があります。

于 2009-08-18T16:08:06.710 に答える