web-dev-qa-db-ja.com

製品、カテゴリ、ラベルを含む3者間関連をモデル化する方法は?

次の3つのテーブルがあります。

products:
    product_id,
    product_name,
    ...

categories:
    category_id,
    category_name,
    category_parent_id,
    category_priority (for sort ordering),
    .....

labels:
    label_id,
    label_name,
    .....

アイデアは、productscategoryに割り当てられると、 categorybylabelsによってWebサイトに次のようにリストされます。

---label1---
product_1
product_2
product_3
---label2---
product_4
product_5
---label3---
product_6
product_7
product_8
product_9
etc.

これらすべてを結び付けて、次のような異常を防ぐ関連付けテーブルを設計する方法がわかりません。

---label1---
product_1
product_2
---label2---
product_2
product_3

同時に、ラベルカテゴリに割り当てられない状況を許可します正当化するのに十分なproductsがない場合。

ご質問

それをまとめる構造を設計することは可能ですか、それとも「すべての希望を捨てて」次のようなものに行くべきですか?

categories:
    category_id,
    category_name,
    category_parent_id,
    categor_is_label,
    category_priority

products:
    product_id,
    product_name,
    ...

それに続く関連テーブル:

categories_products:
    category_id,
    product_id,
    priority

すべてのロジックを処理し、アプリケーションの異常をチェックしますか?

ユーザーがデータベースに直接アクセスできないと想定しています。

コメントとチャットの相互作用

お手元のビジネスコンテキストについての詳細な会話に興味がある方は、 このチャットルーム にアクセスしてください。

2
yemet

注:この回答は、コメントとチャットの対話の最も初期のシリーズによって派生したビジネスルールを具体的にカバーするためのアプローチを示します(そのほとんどは この質問の改訂 それにもかかわらず、より詳細な 明確化と審議 が行われた後、 @yemet は、異なるビジネスルールの連続した識別のために、ビジネスコンテキストが多少異なる方法を必要とする可能性があることを示しました


関心のあるエンティティタイプ(一度実装されたテーブル)に関連する三元関連付け三元またはひし形関係とも呼ばれます)が存在すると判断したという事実は、あなたは正しい方向に向かっています。

ビジネスルール

目的は、実装の側面を完全に検討する前に、論理レベル分析から始めて、手元にある3つの異なる関係を個別に処理することです。この点で、関連するビジネスルールを説明するいくつかの定式化を書き留めることは非常に役立ちます。例:

まず、次の多対多(M:N)の関係についてです。

  • A product is classified by one-to-many categories
  • A category classifies zero-one-or-many products

これは、私がproduct_categoryと呼ぶ連想エンティティタイプの存在を意味します。

次に、明確なM:N関係の場合:

  • A category is integrated by zero-one-or-many labels
  • A label integrates zero-one-or-many categories

別の関連エンティティタイプがあることを示唆する状況。この場合は、category_labelという名前にします。

次に、別のM:N関係を管理する時が来ました。今回は、上記で説明した2つの関連エンティティタイプ間の関係です。

  • A product_category may receive zero-one-or-many label_assignments
  • A category_label may take part in zero-one-or-many label_assignments

前述のように、label_assignmentと名付けた新しいエンティティタイプを含めましたが、当然、ビジネスドメインに関してより意味のある用語を使用して名前を付けることができます。

質問に含まれているcategoriesテーブル(具体的には列categories.category_parent_id)の構造に基づいて、自己再帰1対多(1 :M)categoryというエンティティタイプに関する関係。その後、そのような状況を確認したため、次のルールも適用されます。

  • A category comprises zero-one-or-many categories

論理モデル

次に、IDEF1Xを導出しました1図1

Figure 1 - Product Classification Data Model

この配置により、次の理由により、ニーズの多くを解決できます。

  • 製品は、ラベルの割り当てを受け取る前に、まず特定のカテゴリに関連付ける必要があります。
  • 以前に特定のカテゴリに接続されていない場合、ラベルを特定の製品割り当てすることはできません。
  • 製品は、ラベルとの関係に関与しなくても、特定のカテゴリに関連付けることができます。

解説DDL構造

そのため、次のDDL構造をコーディングしました( SQL Fiddle )でテスト):

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- As one would expect, you are free to make use of 
-- your preferred (or required) naming conventions.

CREATE TABLE product
(
     product_id       INT      NOT NULL,
     product_code     CHAR(30) NOT NULL,
     name             CHAR(30) NOT NULL,
     description      CHAR(90) NOT NULL,
     created_datetime DATETIME NOT NULL,
     CONSTRAINT PK_product             PRIMARY KEY (product_id),
     CONSTRAINT AK_product_code        UNIQUE      (product_code), -- (Possible?) ALTERNATE KEY.
     CONSTRAINT AK_product_name        UNIQUE      (name),         -- ALTERNATE KEY.
     CONSTRAINT AK_product_description UNIQUE      (description)   -- ALTERNATE KEY.
);

CREATE TABLE category
(
    category_number         INT      NOT NULL,
    parent_category_number  INT      NULL, -- Set up as ‘NULLable’, in order to focus on the main aspects of the approach exposed.
    name                    CHAR(30) NOT NULL,  
    description             CHAR(90) NOT NULL,
    created_datetime        DATETIME NOT NULL,
    CONSTRAINT PK_category                         PRIMARY KEY (category_number),
    CONSTRAINT AK_category_name                    UNIQUE      (name),        -- ALTERNATE KEY.  
    CONSTRAINT AK_category_description             UNIQUE      (description), -- ALTERNATE KEY.
    CONSTRAINT FK_FROM_category_TO_parent_category FOREIGN KEY (parent_category_number)
        REFERENCES category  (category_number)
);

CREATE TABLE label
(
    label_number     INT      NOT NULL,
    name             CHAR(30) NOT NULL,    
    description      CHAR(90) NOT NULL,  
    created_datetime DATETIME NOT NULL,
    CONSTRAINT PK_label             PRIMARY KEY (label_number),
    CONSTRAINT AK_label_name        UNIQUE      (name),       -- ALTERNATE KEY.
    CONSTRAINT AK_label_description UNIQUE      (description) -- ALTERNATE KEY.  
);

CREATE TABLE product_category -- Associative table.
(
    product_id          INT      NOT NULL,
    category_number     INT      NOT NULL, 
    classified_datetime DATETIME NOT NULL,  
    CONSTRAINT PK_product_category                  PRIMARY KEY (product_id, category_number),
    CONSTRAINT FK_FROM_product_category_TO_product  FOREIGN KEY (product_id)
        REFERENCES product  (product_id),
    CONSTRAINT FK_FROM_product_category_TO_category FOREIGN KEY (category_number)
        REFERENCES category (category_number)
);

CREATE TABLE category_label -- Associative table.
(
    category_number     INT      NOT NULL,
    label_number        INT      NOT NULL,   
    integrated_datetime DATETIME NOT NULL,  
    CONSTRAINT PK_category_label                  PRIMARY KEY (category_number, label_number),
    CONSTRAINT FK_FROM_category_label_TO_category FOREIGN KEY (category_number)
        REFERENCES category (category_number),
    CONSTRAINT FK_FROM_category_label_TO_label    FOREIGN KEY (label_number)
        REFERENCES label    (label_number)
);

CREATE TABLE label_assignment -- Associative table that ‘concretizes’ a relationship between two distinct relationships.
(
    product_id        INT       NOT NULL,
    category_number   INT       NOT NULL,
    label_number      INT       NOT NULL,  
    assigned_datetime DATETIME  NOT NULL,
    CONSTRAINT PK_label_assignment                          PRIMARY KEY (product_id, category_number, label_number), -- Composite PRIMARY KEY.
    CONSTRAINT FK_FROM_label_assignment_TO_product_category FOREIGN KEY (product_id, category_number)   -- Composite FOREIGN KEY.
        REFERENCES product_category (product_id, category_number),
    CONSTRAINT FK_FROM_label_assignment_TO_category_label   FOREIGN KEY (category_number, label_number) -- Composite FOREIGN KEY.
        REFERENCES category_label   (category_number, label_number)
 );

label_assignment属性が両方に含まれているため、category_numberテーブルの2つの複合FOREIGN KEY定義に特に注意してください。

次のことを規定する要件を提示しました。

ショップで表示するには、製品カテゴリに割り当てる必要があります。

したがって、ここで連想テーブルに行を挿入することにより、product行を挿入するたびにリンク特定のcategoryでそれを確実に挿入する必要があります。 product_categoryと呼ばれます。このように、両方の操作は同じ ACID TRANSACTION 内で実行する必要があります。これにより、単一ユニットとして成功または失敗します。

同様のシナリオ

あなたは私の答えを助けるかもしれません

そして @Ypercubeᵀᴹ


文末脚注

1.情報モデリングの統合定義( IDEF1X )は、米国国立標準技術研究所(NIST)によって1993年12月に標準として確立された、非常に推奨されるデータモデリング手法です。 )(a) Relational Modelオリジネーターが作成した理論的研究、つまり Dr. EF Codd ;(b) Entity-Relationship viewDr。PP Chen ;および(c)によって開発された論理データベース設計技法、Robert G. Brownによって開発されました。IDEF1Xが一次論理によって形式化されたことは注目に値します。

5
MDCCL