あなたが望む解決策は本当にあなたのデータに依存し、そして何千回も前に尋ねられた質問です。エンティティ属性値と厳密なリレーショナルモデルをグーグル
で検索すると、利用可能な方法を比較対照する無数の記事が表示されます。
厳密なリレーショナルモデル
各スキルの顧客テーブルに、追加のフィールドBIT
またはDATETIME
フィールド(NULL
日時がスキルを持たない顧客を表す場合)を追加します。これは、時間の経過とともに大きく変化する可能性が低いスキルがほとんどない場合にうまく機能します。これにより、特にスキルのさまざまな組み合わせで、スキルを持つ顧客を簡単なクエリで見つけることができます。
SELECT *
FROM Customer
WHERE Skill1 >= '20120101' -- SKILL 1 AQUIRED AFTER 1ST JAN 2012
AND Skill2 IS NOT NULL -- HAS SKILL 2
AND Skill2 IS NULL -- DOES NOT POSSESS SKILL 3
エンティティ-属性-値モデル
値はレコードの存在によって表されるブール値であるため、これは従来のエンティティ-属性-値モデルのわずかな適応です。次のようなテーブルを作成します。
CREATE TABLE CustomerSkills
( CustomerID INT NOT NULL,
SkillID INT NOT NULL
PRIMARY KEY (CustomerID, SkillID),
FOREIGN KEY (CustomerID) REFERENCES Customer (ID),
FOREIGN KEY (SkillID) REFERENCES Skills (ID)
)
スキルがいつ追加されたか、誰が追加したかなどを追跡するために、DateAdded、AddidedByなどの追加の列が必要な場合がありますが、コア原則は上記から収集できます。この方法では、列を追加する必要がないため、スキルを追加するのがはるかに簡単ですが、単純なクエリをはるかに複雑にすることができます。上記のクエリは、次のように記述する必要があります。
SELECT Customer.*
FROM Customer
INNER JOIN
( SELECT CustomerID
FROM CustomerSkills
WHERE SkillID IN (2, 3) -- SKILL2,SKILL3
OR (SkillID = 1 AND DateAdded >= '20120101')
GROUP BY CustomerID
HAVING COUNT(*) = 2
AND COUNT(CASE WHEN SkillID = 3 THEN 1 END) = 0
) skills
ON Skills.CustomerID = Customer.ID
これは、リレーショナルモデルよりもはるかに複雑でリソースを大量に消費しますが、全体的な構造ははるかに柔軟です。
要約すると、それは実際にはあなた自身の特定の状況に依存します。考慮すべきいくつかの要因がありますが、決定に役立つリソースはたくさんあります。