ルックアップテーブルの適切な使用


25

データベースでルックアップテーブルを使用するタイミングと場所に適切な境界を設定する方法を正確に把握するのに苦労しています。私が見たほとんどの情報源は、あまり多くのデータを保持することはできないと言っていますが、ある時点で、データベースは非常に多くの部分に分割されるように見えるため、効率的ではあるが、管理できなくなります。ここに私が取り組んでいるもののスローされた例があります:

Employeesというテーブルがあるとします。

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

データがより複雑で、数百の行が含まれていると仮定します。ルックアップテーブルに移動できる最も明らかなものは、Positionです。Positionsというテーブルを作成し、Positionsテーブルの外部キーをPositions列のEmployeesテーブルに貼り付けることができます。

ID  Position
1   Manager
2   Sales

しかし、情報が管理不能になる前に、どの程度まで情報を小さなルックアップテーブルに分解し続けることができますか?別のルックアップテーブルで、性別テーブルを作成し、1を男性に、2を女性に対応させることができます。LNameとFNameをテーブルに入れることさえできました。すべての「John」エントリは、ID 1がJohnに対応することを示すFNameテーブルを指す外部キー1に置き換えられます。ただし、このウサギの穴をあまりにも下に移動すると、Employeesテーブルは大量の外部キーになります。

ID  LName   FName   Gender  Position
1   1       1       1       1
2   1       2       2       2
3   2       1       1       2

これは、サーバーの処理が効率的である場合とそうでない場合がありますが、これを維持しようとしている通常の人には間違いなく読めず、アプリケーション開発者がアクセスしようとするのが難しくなります。だから、私の本当の質問は、どこまで遠すぎるのですか?この種のことに対する「ベストプラクティス」または適切な一連のガイドラインはどこかにありますか?私が現在抱えているこの特定の問題について、有用で有用な一連のガイドラインを実際に特定する情報をオンラインで見つけることはできません。データベース設計は私にとって古い帽子ですが、良いデータベース設計は非常に新しいので、過度に技術的な答えが頭上にあるかもしれません。助けていただければ幸いです!


5
「ルックアップ」テーブルの使用は1つのことです。テキストをID番号に置き換えることは、まったく別のものです。
マイクシェリル 'キャットリコール'

1
性別は常に2つの値に固定されるとは限りません!性別の移行が完了しました。つまり、アプリケーションは「生まれた今すぐメス」や「生まれた今メス」といった追加のカテゴリを必要としないかもしれません。

@マイク、良いコメント!
ウォルターミッティ

私の店では、思想家は、男性、女性、トランスジェンダーの4つの選択だけが開示しなかった後に停止することができました。
ケビンスキー

回答:


22

しかし、情報が管理不能になる前に、どの程度まで情報を小さなルックアップテーブルに分解し続けることができますか?別のルックアップテーブルで、性別テーブルを作成し、1を男性に、2を女性に対応させることができます。

2つの異なる問題が混在しています。1つの問題は、「ルックアップ」テーブルの使用です。もう1つは、代理キー(ID番号)の使用です。

この表から始めます。

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

このようなポジションの「ルックアップ」テーブルを作成できます。

create table positions (
  pos_name varchar(10) primary key
);

insert into positions
select distinct position 
from employees;

alter table employees
add constraint emp_fk1
foreign key (position) 
  references positions (pos_name);

元のテーブルは、「ルックアップ」テーブルを作成する前とまったく同じように見えます。また、従業員のテーブルには、人間が読める有用なデータを取得するために追加の結合は必要ありません

「ルックアップ」テーブルを使用すると、これに要約されます。アプリケーションは、外部キー参照が提供する入力値を制御する必要がありますか?その場合、いつでも「ルックアップ」テーブルを使用できます。(サロゲートキーを使用するかどうかに関係なく。)

場合によっては、設計時にそのテーブルを完全に設定できる場合があります。その他の場合、ユーザーは実行時にそのテーブルに行を追加できる必要があります。(そして、おそらく、新しいデータをレビューするためにいくつかの管理プロセスを含める必要があります。)実際にISO標準を持っている性別は、設計時に完全に設定できます。国際的なオンライン製品注文の番地は、おそらく実行時に追加する必要があります。


2
そんなことができるとは知りませんでした!メソッドの仕組みはとても美しいです。ありがとうございました!
ブラッドターナー

4
この回答に投票できるように、DBA Stack Exchangeに参加しました。これは美しく、私には決して起こりませんでした。ありがとう!
CindyH

ルックアップテーブルにデータを入力する方法に感謝します。この質問を読んだ私の理由は、ルックアップテーブルの代理キーには見られない利点があるかどうかを確認することでした。単一のテキストフィールドが、表示されるのと同じくらい便利で便利であることを確認してくださいました。ありがとうございました。
シンシアV

8

Employeesテーブルでは、「Position」のルックアップしかありません。これは、展開できるデータのセットが限られているためです。

  • 性別は自己記述(MまたはF)であり、2つの値に制限されており、CHECK制約で強制できます。新しい性別は追加しません(政治的正当性の塊を無視します)
  • 最初の名前「ジョン」は、制限された制限されたデータセットの一部ではありません。

新しい位置を追加する場合は、ルックアップテーブルに行を追加するだけです。これにより、正規化の1つのポイントであるデータ変更の異常も削除されます。

また、100万人の従業員がいると、varcharよりもtinyint PositionIDを保存する方が効率的です。

新しい列「給与通貨」を追加しましょう。ここでは、CHF、GBP、EUR、USDなどのキーを持つルックアップテーブルを使用します。代理キーは使用しません。これは、性別などのCHECK制約で制限される可能性がありますが、位置などの制限されたまだ拡張可能なデータのセットです。この例は、tinyintではなくchar(3)であるにもかかわらず、従業員データの数百万行に表示される場合でも、自然キーを使用するためです。

したがって、要約するには、ルックアップテーブルを使用します

  1. 列内に有限であるが拡張可能なセットデータがある場合
  2. どこが自己記述的ではない
  3. データ変更の異常を回避するため

1
性別をルックアップテーブルに入れる1つの考えられる理由は、ローカリゼーションです。
a_horse_with_no_name

1
「性別...(MまたはFなど)、2つの値に制限...政治的正当性の大群を無視」-皮肉なことに、人々が間違って「性別」( ' 「男性」、「女性」)「セックス」(「男性」、「女性」)を意味する場合。コンテキストが文法的な性別である場合、通常は3つ以上の値があります。コンテキストが新生児の性別を記録している場合、少なくとも4つの値があります(「公式に評価されていない」および「公式に評価されていません」)。psの私は、過酷な音を意味するものではありません、私は皮肉:)楽しんで
onedaywhen

4
@onedaywhen:「Sex」という列の正しい値は「Yes please」です。あなたがイギリス人で
-gbn

この用語は正規化に関連する異なる特定の意味を持ち、リンクは不適切であるため、「異常」という用語はここでは誤用されています。
philipxy 14

5

答えは「依存する」です。あまり満足できるものではありませんが、デザインを押したり引いたりする多くの影響があります。データベースを設計するアプリプログラマーがいる場合、ORMが複雑さを隠しているので、あなたが説明するような構造が彼らのために機能します。レポートを作成するときに髪を引き出して、住所を取得するために10個のテーブルを結合する必要があります。

使用目的、使用目的、および将来使用される可能性のある設計。ここでビジネスプロセスの知識が得られます。獣医ビジネス向けのデータベースを設計している場合、機能のサイズ、使用法、および方向について合理的な仮定があります。

お気に入りの引用を再利用するには

「賢い人はかつて「痛くなるまで正常化し、機能するまで非正規化する」と言ったことがあります。

どこかにスイートスポットがあります。私の経験では、複数のテーブルにキーIDを保持することは、主キーを変更しないと考える人ほど深刻な犯罪ではありません。

実際のシステムからの高度に正規化されたテーブルのこの短縮された例を取り上げます

CREATE TABLE PROPERTY
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_TYPE
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_LOCALE 
PROPERTY_ID                  NUMBER(9)           NOT NULL,
(LOCALE_ID                   NUMBER(9)           NOT NULL,  --language 
VALUE                        VARCHAR2(200)       NOT NULL);

CREATE TABLE PROPERTY_DEPENDENCY
(PROPERTY_ID                 NUMBER(9)           NOT NULL,
 PARENT_PROPERTY_ID          NUMBER(9)                   ,
 PROPERTY_TYPE_ID            NUMBER(9)           NOT NULL);

これらのテーブルは、単一のプロパティと親子プロパティのリンクリストを設定し、ここで使用されます

  CREATE TABLE CASE_PROPERTY
  (ID                        NUMBER(9)           NOT NULL,
  PARENT_ID                  NUMBER(9),
  CASE_ID                    NUMBER(9)           NOT NULL,
  PROPERTY_ID                NUMBER(9),
  PROPERTY_TYPE_ID           NUMBER(9)           NOT NULL);

これは問題ありません:1回の選択でproperty_idを持つすべてのケースを取得します

選択するリストを取得しましょう

 Select pl.value, pd.property_id
 from property_locale pl, property_dependency pd
 where pl.property_id = pd.property_id
 and pd.property_type_id = 2;  --example number

ケースのproperty_typesが3および4および5であるかどうかにかかわらず、ケースのすべてのプロパティを選択してみてください...

SELECT   cp2.case_id,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 2
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE1,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 34
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE2,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 4
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE3
  FROM   case_property cp2
 WHERE   cp2.case_id = 10293  

これはただ痛い...これをもっとエレガントな方法で扱うときでも。ただし、ケースがproperty_idを1つだけ持つプロパティを分割することにより、少し正規化を追加します。

テーブルが多すぎたり、十分でない場合は、アプリケーション、レポート、および年ごとの分析で質問してデータベースを照会してみてください。


5
ID番号は正規化とは関係ありません。すべてのテーブルにID番号があるからといって、5NF、または3NFであることを意味しません。そのテーブルから使用可能なデータを取得するには、多くの結合を行う必要があることを意味します。
マイクシェリル 'キャットリコール'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.