web-dev-qa-db-ja.com

企業と株式所有者のためのデータベース構造の設計

私はすべての公開企業のすべての所有者の情報を保持するデータベースを作成したい個人的なプロジェクトに取り組んでいます。たとえば、「Sears INC」と言うと、プログラムは「Sears INC」のすべての所有者の情報を取得します。それがアイデアです。しかし、私はこのデータベースを構築しようとするのに本当に苦労しています。私はこの主題について限られた経験と知識しかないので、どんなガイダンスもいただければ幸いです。

私は最初に、会社というテーブルを作成することを考えていました。それらにすべての一意のIDを与え、すべての会社のテーブルを作成しました。次に、それらのテーブル内には、一意のIDを持つすべての所有者が含まれます。それは彼らの情報にリンクするでしょう。これをここで視覚化しようとしました:

here

すべての会社のテーブルを作成するのは面倒なことですが、これを行う他の方法は考えられません。ご存じのとおり、各会社の所有者は同じであるため、Owner_IDを使用して各所有者を識別することは理にかなっています。

他のすべてのデータはCVSファイルにあり、データベースを構造化した後でPostgreSQLに簡単にインポートできます。

どんな助けでも大歓迎です。

TL:DR;会社名で検索できる株の所有者のデータベースを作成し、最大の効果を得るためにデータベースを構築するための支援が必要です。

人は1つの電話と1つのアドレスしか持てません。この情報に基づいて電話を検索するスクリプトを作成したので、会社についても同じです。エンティティが会社なのか個人なのかを区別する方法は、F_Orgと呼ばれる列を使用することです。これは、会社では4桁より大きくなります。これはすべてスクリプトによって処理されます。

5
Jane Doe

データベース設計の回答でよく触れるトピックの1つは、(a)リレーショナルデータベースの技術的な側面(たとえば、テーブルや列の宣言など)を考える前に、まず(b)を強くお勧めします。関心のあるビジネスコンテキストのすべての特性を正確に定義します。これは、エンティティタイプ、そのプロパティ、およびエンティティ間に存在するすべての重要な関連付けを識別することを意味します。

上記の要素に関する定義のグループは、一般にビジネスルールと呼ばれ、適用可能な概念モデルを構成します。

また、(1)データ管理と(2)リレーショナルデザインと操作については、(3)質問やコメントで取り上げたいくつかの側面を明確にするのに役立つ可能性がある他の重要なテーマがあると思います。答えが進むにつれ、これらすべてのポイントを統合します。

概念レベル

抽象化の関連する概念レベルの再評価を始めましょう。この点で、ビジネス環境を説明する一連のステートメントを作成することが重要です。したがって、特定のケースでは、ビジネスルールを意図的にできるだけシンプルに保つ必要があります。

  • 会社は主にIdで識別されます
  • Companyは、代わりにNameで識別されます
  • CompanyFoundingDateに設定されます
  • A Personは主に彼または彼女によって識別されますId
  • Personは、彼または彼女の組み合わせによって交互に識別されますFirstNameLastNameGenderCodeBirthDateおよびBirthPlace
  • A Personは正確に1つを保持しますAddress
  • A Personは厳密に1つを使用しますPhoneNumber
  • A Companyは1対多の所有People
  • A Personは1つまたは複数のゼロを所有Companies

説明的なIDEF1Xモデル

次に、上記で定式化されたビジネスルールに基づいて、意図的に比較的単純なIDEF1Xを作成できます。a図1 に示すようなモデルを使用して、重要な機能のほとんどを単一のリソースに統合するグラフィカルデバイスを作成します。

Figure 1 - Companies and Stock Owners Simplified IDEF1X Model

a情報モデリングの統合定義IDEF1X )は、1993年12月に標準として確立された、非常に推奨されるデータモデリング手法です。米国National Institute of Standards and Technology(NIST)。これは、(a)リレーショナルモデルの創始者、 Dr。 E. F.コッド ; (b) エンティティ関係ビューDr。 P. P.チェン ;また、(c)Robert G. Brownが作成した論理データベース設計手法についても説明します。

示されているように、IDEF1Xモデルでは、論理レベルでのPRIMARY、ALTERNATE、およびFOREIGN KEYの定義(簡潔にするために、それぞれPK、AK、およびFK)を介して制約する必要があるプロパティまたは属性の表示などの技術的な考慮事項を含めることができます。

前に説明したビジネスルールの最後の2つは、エンティティタイプCompanyPersonの間に多対多(M:N)の関連付けまたは関係があることを示しています。これにより、CompanyOwnerCompanyShareHolderと呼ばれるか、ビジネスドメインで使用される用語をより適切に表すものとなるでしょう)。

現在のモデリング演習で特に重要な特性の1つは、StockShareQuantity関連付けのコンテキストでのみ発生するため、CompanyOwnerという名前のプロパティです([Sharesの合計を表す))。このように、それはPersonにもCompanyにも属していませんが、これら2つの別個のエンティティタイプ間で発生する可能性のある接続に属しています。

指定したとおり、各CompanyOwnerオカレンスまたはインスタンスは、そのCompanyId値とOwnerId値の組み合わせによって識別されるため、これらのプロパティはエンティティタイプの図で複合PKとして強調表示されます。 CompanyOwner.CompanyIdプロパティはCompany.CompanyIdを指すFKで区別され、CompanyOwner.OwnerIdPerson.PersonIdを参照するFKで示されます。

少し複雑なPersonエンティティタイプを描くことを目指して、Person.NameFirstNameLastNameに分解し、列GenderCodeBirthDateBirthPlaceを含めました。これらのすべてのプロパティを組み合わせた値は、通常、特定のビジネスシナリオでPersonを識別するために使用されますが、Person.FullNameを追跡することで、データ使用の要件を満たすことができます。議論中の特定のデータベースに関して同じアプローチに従う必要はありません。

説明的な論理SQL-DDL構造

その後、データベース管理システムが提供するデータ定義言語(この場合はPostgreSQL)を使用して論理構造を宣言する方が比較的簡単です。以下に例を示します。

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

-- Also, you should make accurate tests to define the
-- most convenient physical implementation settings; e.g.,
-- a good INDEXing strategy based on query tendencies.

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

CREATE TABLE Company ( -- Stands for an independent entity type
    CompanyId       INT       NOT NULL, -- You may like to set it with the SERIAL type to retain system-assigned and system-generated surrogate values.
    Name            TEXT      NOT NULL,
    FoundingDate    DATE      NOT NULL,
    Etcetera        TEXT      NOT NULL,
    CreatedDateTime TIMESTAMP NOT NULL DEFAULT NOW(), -- You may also configure it so that the DEFAULT value is set by the CURRENT_TIMESTAMP function, if appropriate. 
    --
    CONSTRAINT Company_PK PRIMARY KEY (CompanyId),
    CONSTRAINT Company_AK UNIQUE      (Name) -- Single-colum ALTERNATE KEY.
);

CREATE TABLE Person ( -- Denotes an independent entity type.
    PersonId        INT       NOT NULL, -- You may like to set it with the SERIAL type to retain system-assigned and system-generated surrogate values.
    FirstName       TEXT      NOT NULL,
    LastName        TEXT      NOT NULL,
    GenderCode      TEXT      NOT NULL,
    BirthDate       DATE      NOT NULL,
    BirthPlace      TEXT      NOT NULL,  
    Address         TEXT      NOT NULL,   
    PhoneNumber     TEXT      NOT NULL,     
    CreatedDateTime TIMESTAMP NOT NULL DEFAULT NOW(), -- You may also configure it so that the DEFAULT value is set by the CURRENT_TIMESTAMP function, if appropriate.
    --
    CONSTRAINT Person_PK PRIMARY KEY (PersonId),
    CONSTRAINT Person_AK UNIQUE      ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate,
        BirthPlace
    )
);

CREATE TABLE CompanyOwner ( -- Represents an associative entity type or M:N association. Attaching an extra column to hold system-generated and system-assigned surrogate values to this table is superfluous.
    CompanyId          INT       NOT NULL,
    OwnerId            INT       NOT NULL,
    StockShareQuantity INT       NOT NULL,
    Etcetera           TEXT      NOT NULL,  
    CreatedDateTime    TIMESTAMP NOT NULL DEFAULT NOW(), -- You may also configure it so that the DEFAULT value is set by the CURRENT_TIMESTAMP function, if appropriate. 
    --
    CONSTRAINT CompanyOwner_PK          PRIMARY KEY (CompanyId, OwnerId), -- Composite PRIMARY KEY.
    CONSTRAINT CompanyOwnerToCompany_FK FOREIGN KEY (CompanyId)
        REFERENCES Company (CompanyId),
    CONSTRAINT CompanyOwnerToPerson_FK  FOREIGN KEY (OwnerId)
        REFERENCES Person (PersonId),
    CONSTRAINT StockShareQtyIsValid_CK  CHECK       (StockShareQuantity >= 0) -- Appears to be required.
);

説明したように、この意図的で比較的単純な論理構造ではb (これは、ダイアグラムに描かれているものと非常に似ていますが、いくつかの重要な違いがあります):

  • ベーステーブルは、あいまいさを防ぐ個々のエンティティタイプを示します。
  • columnは、それぞれのエンティティタイプの単一のプロパティを表します。
  • 特定のデータタイプが各に固定され、保持するすべてのが特定のセット( PostgreSQL )によって提供されるオプションから最も適切なタイプを選択して、INT、TIMESTAMP、TEXTなど、あなたの正確な必要性に適応するように適応します。そして
  • 複数の制約c、d すべてのテーブルで保持されるrowsが概念モデルで決定された規則に準拠することを保証するために、(宣言的に)設定されます。

bdb <> fiddleSQL Fiddle をアップロードしました。これらは、私が一緒に定義したDDL構造と制約を含み、PostgreSQL 9.6で実行されています。 「実際に」テストできるようにサンプルデータを使用します。

c (i)データの構造、つまりテーブル、列、タイプ、および(ii)有効なデータのみを受け入れるようにするためにそのような構造に課された制約(PK、FK、チェックなど)は、(iii)構成の2つの異なる(ただし関連する)要素です。リレーショナルデータベースでは、(iv)構造体宣言を制約宣言とは別に配置することをお勧めします—SQL言語とPostgreSQLによって提供される方言は、そのオプションを選択したい場合は、「インライン」列制約を宣言できます—。実際、制約定義をCREATE TABLE…(…);の外に移動した方がよいでしょう。ステートメントなので、この点は完全な評価に値します。

d制約からの構造の分離に関して私が行う例外は、それがspecial制約の一種であるため、「インライン」列宣言で事実上NOT NULLを修正することです。可能な限り簡潔にするために、NULLマークを許可するというアプローチは、理論的には物議を醸すと見なされているアプローチで、SQL言語の設計者によって導入され、不足している情報の問題を管理しようとしています。次に、NULLマークは、3値論理と呼ばれる別の問題に対処することを意味します。関係理論によれば、NULLマーク(1)を囲む1つ以上の列を持つテーブルはnotは数学的な関係を表します—このマークは値がないことを示すインジケーターであり、ドメインではありません値-したがって、(2)このようなテーブルは、操作されたときにリレーションシップとして「動作」しません。したがって、列にNULLマーカーを維持することは可能ですが、これらのトピックについて信頼できる資料を調べて、欠落データの管理に関するすべての影響と方法を知った上で情報に基づいた決定を下せるようにすることをお勧めします。

Person.Address列

Address列の特定のエンコードされた部分の操作に関心がある場合は、PostCodeとしましょう。いくつかの列で分解して、関連情報を、おそらくPersonに接続される別のテーブルに移動することを検討できます。 FK制約のある列を介したテーブル。

各テーブルの宣言Company

あなたはコメントで以下の考えを持ち出しました:

[…]複数の会社が存在し、人々は複数の会社を所有できるため、デザインが変更されるので、2回表示されます。私の最初の質問は、これをどのように設計するかでした。私は自分の最後の手段になると思う各会社​​のテーブルを作ることを考えましたが、これを行う方法に関する他のガイダンスやヒントはまだありません。

Nonotそれぞれに対してテーブルを作成するCompanyこれは最適ではないためです。

その点で、以前に提示された各ベーステーブルに保持されているすべての行は、特定のタイプに属する特定の概念レベルのエンティティ、つまり次のいずれかについてassertionであると言えます。 CompanyまたはPersonまたはa CompanyOwner

したがって、指定されたCompanyに関する行はCompanyテーブルに保持されますonly onceと指定されたPersonに関する行は維持されます一度だけPersonテーブル内。次に、Personはゼロ、1つ以上のCompaniesを所有できるため、各行はPersonが個人に対して持つ正確な接続に関するものですCompanyCompanyOwnerテーブルで囲まれていますonly once

CompanyOwnerテーブルの行にはPersonに関するすべての情報は含まれていません。(1)OwnerId列の1つの値(FKとして制約されている)のみを含み、(2)1つを参照しますPerson.PersonId列に保持される値—PKとして制約されます—。特定のCompanyOwner.OwnerId値が複数回繰り返される可能性があるため、CompanyOwner.CompanyId値でも発生する可能性がありますが、問題ありません。例示したように、CompanyOwner複合PK定義により、(CompanyId, OwnerId)値の同じ組み合わせを繰り返す可能性が防止されます。

導出可能な情報

ベーステーブルのセットは、リレーショナルデータベースに関しては、固定構造ではありません。拡張や適応の影響を受けやすいだけでなく、ベーステーブルは、設計時に構成されていない新しいテーブルを導出するのに役立ちます。

次のINSERT操作を介して、データベーステーブルにサンプルデータを入力したと仮定します。

INSERT INTO Company 
    (CompanyId, Name, FoundingDate, Etcetera)
VALUES
    (1748, 'Database Modeling Inc.', '1985-06-30', 'Foo'),
    (1750, 'Application Programming Co.', '1987-10-14', 'Bar');

INSERT INTO Person 
    (PersonId, FirstName, LastName, BirthDate, BirthPlace, GenderCode, Address, PhoneNumber)
VALUES
    (1, 'Edgar', 'Codd', '1923-08-19', 'Fortuneswell, UK', 'M', 'IBM Research Laboratory K01/282, 5600 Cottle Road, San Jose, CA, USA', '01-800-17-50-17-50'),
    (2, 'Alan', 'Turing', '1912-06-23', 'Maida Vale, UK','M', 'National Physical Laboratory, Hampton Road, Teddington, TW11 0LW, England', '01-800-17-48-17-48'),
    (3, 'Grace', 'Hopper', '1906-12-09', 'New York City, USA', 'F', 'Navy’s Office of Information Systems Planning, USA.', '01-800-17-50-17-50'),   
    (4, 'Diego', 'Velázquez', '1599-06-06', 'Seville, Spain', 'M', 'Palacio Real, Madrid, Spain', '01-800-17-50-17-50'),
    (5, 'Michelangelo', 'Buonarroti', '1475-03-06', 'Caprese, Italy', 'M', 'Sistine Chapel, Vatican City State', '01-800-17-50-17-50'); 

INSERT INTO CompanyOwner 
    (CompanyId, OwnerId, StockShareQuantity, Etcetera)
VALUES
    (1748, 1, 2500, 'U'),
    (1750, 1, 2500, 'V'),
    (1750, 2, 8000, 'W'),
    (1750, 3, 3580, 'X'),
    (1748, 4, 12899, 'Y'),
    (1750, 5, 12899, 'Z'); 

その後、たとえば、すべてのCompaniesOwnersに関するデータを含むテーブルを作成する場合は、次のようにVIEWを宣言できます。

CREATE VIEW CompanyAndOwner AS
    SELECT C.CompanyId,
           C.Name AS CompanyName,
           P.PersonId,
           P.FirstName,
           P.LastName,
           P.BirthDate,
           P.BirthPlace,
           P.GenderCode,
           P.Address,
           P.PhoneNumber,
          CO.StockShareQuantity,
           P.CreatedDateTime
        FROM Person P
        JOIN CompanyOwner CO
          ON CO.OwnerId = P.PersonId
        JOIN Company C
          ON C.CompanyId = CO.CompanyId;

次に、連続した操作を表現できますc そのビューから直接選択します。例えば。:

SELECT *            
  FROM CompanyAndOwner 
 WHERE CompanyId = 1750;

そして

SELECT CompanyName,
       FirstName AS OwnerFirstName,
       LastName  AS OwnerLastName,
       StockShareQuantity
  FROM CompanyAndOwner 
 WHERE CompanyId = 1750; 

そして

SELECT * 
  FROM CompanyAndOwner 
 WHERE CompanyId = 1748;

そして

SELECT CompanyName,
       FirstName AS OwnerFirstName,
       LastName  AS OwnerLastName,
       StockShareQuantity
  FROM CompanyAndOwner 
 WHERE CompanyId = 1748;

または、ベーステーブルから直接SELECTすることもできます。

SELECT COUNT(OwnerId) AS OwnedCompaniesQuantity
   FROM CompanyOwner
  WHERE OwnerId = 1;

等.

e ここに含まれるすべてのデータ操作操作は、以前にリンクされた db <> fiddle および SQL Fiddle に含まれるため、分析できますそれらが生成する結果セット。

会社の住所と電話番号

コメントを介して行った一連の審議で、会社に属するAddressesおよびPhoneNumbersを保持することに関心があるかどうか、および応答は次のとおりでした:

人は1つの電話と1つのアドレスしか持てません。この情報に基づいて電話を検索するスクリプトを作成したので、同じことが会社にも言えます。エンティティが会社なのか個人なのかを区別する方法は、F_Orgと呼ばれる列を使用することです。これは、会社では4桁より大きくなります。これはすべてスクリプトによって処理されます。

CompanyAddress(es)およびPhone Number(s)がアプリケーションプログラムコンポーネントに格納されていることを意味するかどうかはわかりません(おそらく、レコードとフィールドを含むファイル、または類似のもの)が、実際にその情報を処理している場合は、ジョブに適切なツールを使用する必要があります。つまり、データベース構造にこれらの側面を含め、データベース管理システム(PostgreSQLなど)によって提供される手段。これにより、関係データを最適な方法で管理できます(たとえば、物理レベルでサポートされる、リレーショナル代数と宣言制約に基づく論理レベルの操作により)強力なセット処理エンジンによる)。

スーパータイプとサブタイプの関係を表す実現可能なDDL構造拡張

したがって、あなたがそれを決定した場合、あなたのビジネスドメインで

  • 同じAddressの発生は、複数のPersonおよび/またはCompanyインスタンスで保持できます。

そして

  • 同じPhoneNumberオカレンスを複数のPersonまたはCompanyインスタンスで使用できます。

this answer に含まれている図を分析して、検討中のシナリオと非常に似ているシナリオについての質問を探したいと思うかもしれません(他の機能の中でも特にパーティー組織または人物サブタイプを表すスーパータイプ、役割の再生所有者Organizations、およびAddressesおよびPhoneNumbersOrganizationsおよびPeopleとリンク=スーパータイプを介して)、一時的な拡張機能の参照として使用できるため。

7
MDCCL