web-dev-qa-db-ja.com

チケットまたはタスクを割り当てるためのデータベース設計

以下は、割り当てられたタスク、タスクのテーブルです。ここで、設計に従ってタスクまたはチケットをユーザーに割り当てる必要があります。タスクとチケットの両方を割り当てるためのテーブルを1つだけ作成しました。タスクが割り当てられるとticket_id列がNULLになり、チケットが割り当てられるとtask_idがNULLになるので、1つの列がNULLになるたびに、これがデータベース設計にとって正しい方法であることを知りたいか、タスクとチケットを割り当てるために2つの異なるテーブルを作成する必要があります。 Plzが案内してくれます。

tickets
-------------------------------------------------------------   
id  | title | description | priority | status | created_by  |
-------------------------------------------------------------
1   | tkt1  |this is tkt1 | 1        | 1      | 10          |
-------------------------------------------------------------
2   | tkt2  |this is tkt2 | 3        | 2      | 11          |
-------------------------------------------------------------

tasks
-------------------------------------------------------------------------   
id  | title | description | priority | status | ticket_id   |created_by |
-------------------------------------------------------------------------
1   | tkt1  |this is tkt1 | 2        | 1      | 1           | 23        |
-------------------------------------------------------------------------
2   | tkt2  |this is tkt2 | 2        | 2      | 2           | 23        |
-------------------------------------------------------------------------

Assigned
---------------------------------------------
 id | ticket_id | task_id   | assigned_to   |
---------------------------------------------
1   |   1       |   NULL    |       25      |
---------------------------------------------
2   |   NULL    |   1       |       25      |
---------------------------------------------
3   |   2       |   NULL    |       25      |
---------------------------------------------
4   |   NULL    |   2       |       25      |
---------------------------------------------
3

ほとんどのデザインでは、ある種のトレードオフがあります。あなたが提案したことの欠点の1つは、ASSIGNEDで候補キーを見つけることができないことです。誰かが追加した場合の意味を考えてみましょう:

INSERT INTO ASSIGNED (ID, TICKET_ID, TASK_ID, ASSIGNED_TO)
VALUES (5, 1, NULL, 25);  

私の観点からは、2つのテーブルの方が良いでしょう。

CREATE TABLE ASSIGNED_TICKETS
( USER_ID ... NOT NULL REFERENCES USERS (USER_ID)
, TICKET_ID ... NOT NULL REFERENCES TICKETS (TICKED_ID)
,    PRIMARY KEY (USER_ID, TICKET_ID) );

チケットを複数のユーザーに割り当てることができない場合は、TICKET_IDを主キーにします。

ASSIGNED_TASKSにも同様のテーブルを使用できます。

代わりのデザインはスーパーテーブルを使用することです。より良いWordがないことをWORK_UNITと呼びます。

CREATE TABLE WORK_UNIT
( WORK_UNIT_ID ... NOT NULL PRIMARY KEY
, WORK_UNIT_TYPE CHAR(4) NOT NULL 
,   CHECK (WORK_UNIT_TYPE IN ('TICK', 'TASK'))
, ... );

TICKETTASKの関係は、別のテーブルで表すことができます。

CREATE TABLE TICKES_FOR_TASKS
( TASK_ID ... NOT NULL
      REFERENCES WORK_UNIT (WORK_UNIT_ID)
, TICKET_ID ... NOT NULL     
      REFERENCES WORK_UNIT (WORK_UNIT_ID)
,   PRIMARY KEY (TASK_ID, TICKET_ID) );

その関係にタイプを適用する場合(たとえば、TICKETが他のTICKETSで構成されないようにするため)、WORK_UNITにUNIQUE制約を追加できます。

ALTER TABLE WORK_UNIT ADD CONSTRAINT ...  
    UNIQUE (WORK_UNIT_ID, WORK_UNIT_TYPE)

tICKES_FOR_TASKSのWORK_UNIT_TYPEを「継承」します。

CREATE TABLE TICKES_FOR_TASKS
( TASK_ID ... NOT NULL
, TASK_TYPE CHAR(4) NOT NULL
,     CHECK ( TASK_TYPE = 'TASK' )
,     FOREIGN KEY ... (TASK_ID, TASK_TYPE) 
      REFERENCES WORK_UNIT (WORK_UNIT_ID, WORK_UNIT_TYPE)
, TICKET_ID ... NOT NULL
, TICKET_TYPE CHR(4) NOT NULL
,     CHECK ( TICKET_TYPE = 'TICK' )
,     FOREIGN KEY ... (TICKET_ID, TICKET_TYPE) 
      REFERENCES WORK_UNIT (WORK_UNIT_ID, WORK_UNIT_TYPE)
,   PRIMARY KEY (TASK_ID, TICKET_ID) );

SELECTでCHECK制約をサポートするDBMSについて聞いたことがありますが(自分では使用していません)。その後、型属性を「継承」することを回避できます。これを回避する別の方法は、チケットまたはタスクのタイプが間違っている場合に例外をスローするトリガーを使用することです。

このシナリオでは、ASSIGNMENTSに必要なテーブルは1つだけです。

CREATE TABLE ASSIGNED_WORK_UNITS
( USER_ID ... NOT NULL REFERENCES USERS (USER_ID)
, WORK_UNIT_ID ... NOT NULL REFERENCES WORK_UNIT (WORK_UNIT_ID)
, ... -- additional attributes
,    PRIMARY KEY (USER_ID, WORK_UNIT_ID) );

従来通り。 WORK_UNIT_IDをUSERS間で共有できない場合は、WORK_UNIT_IDを主キーにします。

欠陥のないデザインはないので、考えられるものそれぞれについて慎重に検討する必要があります。うまくいけば、彼はあなたに何を考慮すべきかについていくつかのアイデアを与えるでしょう。

3
Lennart