web-dev-qa-db-ja.com

再帰的な関係のためのデータベース設計

私が会社のデータベースをモデル化しようとしているこのケースを考えてみましょう:

  • エンティティ:EmployeesManagersDepartments
  • Employeeは1つのDepartmentでのみ機能しますが、Departmentには多数のEmployeesが含まれている場合があります。
  • Managerは1つのDepartmentのみを管理でき、同様にDepartmentは1つのManagerのみを管理できます。
  • Managerは多数のEmployeesを監視しますが、Employeeは1つのManagerによってのみ監視されます。

これをモデル化する方法は2つあります:

最初のソリューション:

ManagerエンティティはEmployeeエンティティから継承すると考えます。これは、マネージャに固有のデータ(ボーナスやステータスなど)を保持することを考慮しています。

First Solution

  • DepartmentEmployeeの関係は1:Nなので、EmployeeテーブルのWorksテーブルにDepartment Idを外部キーとして配置します[$ var] _リレーション。

  • DepartmentManagerの関係は1:1なので、ManagerテーブルのManagesテーブルにDepartment Idを外部キーとして配置します[$ var] _リレーション。

問題:ManagerEmployeeの間の再帰的な関係をどのように表すことができますか?


2番目の解:

他のManagerにもEmployeesBonusが含まれている可能性があるため、Statusエンティティは不要であると考えます。 (実際には、両方のケースでモデル化する方法を確認するために、これら2つの属性を追加しました) Second solution

  • DepartmentEmployeeの関係は1:Nなので、EmployeeテーブルのWorksテーブルにDepartment Idを外部キーとして配置します[$ var] _リレーション。
  • EmployeeManagerの関係は1:Nなので、EmployeeテーブルのSupervisesテーブルにEmployee Idを外部キーとして配置します[$ var] _リレーションとそれをManager Idと呼びます。

問題:ManagerDepartmentの関係をどのように表すことができますか?


質問:

  1. どちらのデザインにも明らかな間違いはありますか?
  2. 両方のケースで各問題を解決するにはどうすればよいですか?
  3. これら2つより良い解決策はありますか?
20
Songo

私はおそらく次のようなものに行くでしょう:

enter image description here

このモデルには次の特性があります。

  • マネージャーは従業員を「継承」します。
    • 従業員を表すには、EMPLOYEEに単一の行を挿入します。
    • マネージャーを表すには、EMPLOYEEに1行挿入and MANAGERに1行挿入します。
  • 部門は複数の従業員を持つことができます。
  • すべての部門に1人のマネージャーがいて、すべてのマネージャーが0個または1個の部門を管理しています。
  • スーパーバイザは、一般の従業員またはマネージャです。
  • 部門は「一致」する必要はありません:
    • スーパーバイザは、監視対象の従業員とは別の部門で働くことができます。
    • マネージャは、自分が働いている場所とは別の部門を管理できます。
    • スーパーバイザーがマネージャーである場合、彼が管理する部門、彼が勤務する部門、および彼/彼女の監視対象従業員の部門はすべて異なる場合があります。

注:DBMSが遅延制約をサポートしていない場合は、DEPARTMENT.MANAGER_IDをNULL可能にして、新しいデータの挿入を妨げるサイクルを解除する必要があります。


部門を一致させる必要がある場合は、DBMS固有の手法(トリガーや「特別な」制約など)を使用するか、DEPARTMENT_IDを従業員のPKに「伝播」します。この伝播により、最終的にマッチングが可能になります。

enter image description here

EMPLOYEE_IDはグローバルに一意である必要があるため、DEPARTMENT_IDと一緒に複合キーにとどまることはできません。したがって、これを代替キーにして、代わりにPKで代理EMPLOYEE_NOを使用します。

このモデルでは、ある部門を管理して別の部門で作業するマネージャーや、別の部門の従業員を監督する上司が存在しないようにします。


シンボルに慣れていない場合...

enter image description here

...「カテゴリ」を示します。このコンテキストでは、それをEMPLOYEEとMANAGER間の「1対0または1」の関係として簡単に解釈できます。

26

詳細については説明しませんが、従業員/マネージャー/部門のソリューションは、長期的には不快感の源(最初は)であり、次にデータベースの保守担当者にとって本当のPITA(後で)であることを保証します。 /またはそのインターフェースを開発する。だから私はあなたの2番目の提案を守ることをお勧めします。

マネージャー/部門の関係については、主にこの関係を表す2つの方法があります。どちらのソリューションでも、次のように実装できる「マネージャーが部署を管理する」関係に加えて、再帰的な「マネージャーが従業員を管理する」関係を維持することができます。

1-最初の/簡単な方法:部門テーブルにマネージャー/従業員IDを追加します。このフィールドはもちろん、従業員テーブルへの外部キーです

2-2番目/より複雑なソリューション:次のフィールドを持つ「マネージャー」テーブルを追加します。

Manager id (PK, surrogate)
Department id (FK)
Employee id (FK)
beginningDate
endingDate

管理履歴を保存する場所:誰から、どの部門に対して、いつから、いつまで

この場合、ビジネスルールを変換するためのロジック(トリガー、またはクライアント側の制御)を追加することを忘れないでください。たとえば、特定の期間と特定の部署には1人のマネージャーしか存在できず、部署はこれ以上滞在できません...マネージャーなしなど.

編集:

3-より豊かなソリューションは、私の2番目の提案を一般化したものであり、会社の全員のキャリアを追跡できるようにします。これは次のような「機能」テーブルで実行できます(ここでは「位置」テーブルと呼んでいるので、ここでは同じ用語を使用します:

Position id (PK, surrogate)
Department id (FK)
Employee id (FK)
Position Level (FK)
beginningDate
endingDate

「職位レベル」は、部門に存在する可能性のあるさまざまな職階を保持する別のテーブルにつながりますが、その1つはもちろん「マネージャー」の職位です。

この提案は、人事データベースとソフトウェアで使用されているものにより近く、そのような複雑なソリューションは必要ないかもしれません。ただし、人間を複数のテーブルに分割することは常に間違いであることを覚えておいてください。

編集:あなたのコメントに従って...

わかりやすくするために、フィールド名を調整することをお勧めします。次のフィールドを用意することをお勧めします。

Tbl_Employee.id_EmployeeManager

そして

Tbl_Department.id_DepartmentManager

これにより、私たち(または開発者)は、id_EmployeeManagerが個人間の再帰的な関係に参加し、id_DepartmentManagerが個人と部門間の関係に参加することをすぐに理解できます。

あなたの質問に戻って、私によれば、あなたは次のリンクを作成すべきではありません:

Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_EmployeeManager

そうすることで、誰かが部長になれないことを意味しますunless彼はすでに従業員を管理しています。従業員が1人の部門についてはどうですか?従業員がまだ割り当てられていない、新しく作成された部門のマネージャーという名前の人はどうですか?それは動作しません。正しいリンクは次のとおりです。

Tbl_Department.id_DepartmentManager -> Tbl_Employee.id_Employee

もちろん、たとえば、「部署を管理する従業員はマネージャーのみになることができる」(id_Employeeはid_EmployeeManagerとしてどこかに存在する)、または「部署を管理する従業員はマネージャーを持つことができない(この従業員のid_EmployeeManagerはnullである)」というビジネスルールを追加できます。 ...)しかし、これらはビジネスルールにすぎません。データモデルは、基本的なルールが守られている限り、つまり部署が従業員によって管理されている限り、すべてのルールを受け入れることができます。

1

私の意見:

従業員とマネージャーの両方の情報を追加するテーブルパーソン、マネージャーも人間ですよね? :)、そしてあなたはマネージャーのIDにリンクするmanagerIdフィールドを持っています。

部門情報を含むテーブル部門

また、従業員が複数の部門に所属できる場合は、それらを関連付けるためにテーブルemployee_departmentを作成します。従業員が所属できる部門が1つだけであり、関係の詳細が必要ない場合は、EmployeeテーブルにdepartmentIDフィールドを追加します。

0
Diego

私はこれが最良の解決策だと思います:

DB Design

マネージャーは、部門を管理する従業員です。次のフローで取得できる再帰関係:

従業員は部門を持っています部門はマネージャーとして従業員を持っています

たぶん、ロールを定義するために従業員テーブルにEmployeeType列を与えるのに便利です。

0
pascalvgemert

2つ目のデザインにこだわって疑似関係を作ってみませんか?

従業員エンティティと部門エンティティ間の関係をリンクするために、従業員エンティティにdepartment_id列があることを想定しています。マネージャー階層(マネージャーのマネージャー)がないと想定できる場合は、2つのテーブル間に擬似関係を適用できます。ここで、マネージャーのDepartment_IDManager_IDはNull)は部門を表します管理する。

これを明確に文書化している限り、Departmentエンティティを参照するEmployeeエンティティにFK列(department_id)が既にあるので、スペース効率の良いアプローチになると思います。

0
Ellest