私はすべての公開企業のすべての所有者の情報を保持するデータベースを作成したい個人的なプロジェクトに取り組んでいます。たとえば、「Sears INC」と言うと、プログラムは「Sears INC」のすべての所有者の情報を取得します。それがアイデアです。しかし、私はこのデータベースを構築しようとするのに本当に苦労しています。私はこの主題について限られた経験と知識しかないので、どんなガイダンスもいただければ幸いです。
私は最初に、会社というテーブルを作成することを考えていました。それらにすべての一意のIDを与え、すべての会社のテーブルを作成しました。次に、それらのテーブル内には、一意のIDを持つすべての所有者が含まれます。それは彼らの情報にリンクするでしょう。これをここで視覚化しようとしました:
すべての会社のテーブルを作成するのは面倒なことですが、これを行う他の方法は考えられません。ご存じのとおり、各会社の所有者は同じであるため、Owner_IDを使用して各所有者を識別することは理にかなっています。
他のすべてのデータはCVSファイルにあり、データベースを構造化した後でPostgreSQLに簡単にインポートできます。
どんな助けでも大歓迎です。
TL:DR;会社名で検索できる株の所有者のデータベースを作成し、最大の効果を得るためにデータベースを構築するための支援が必要です。
人は1つの電話と1つのアドレスしか持てません。この情報に基づいて電話を検索するスクリプトを作成したので、会社についても同じです。エンティティが会社なのか個人なのかを区別する方法は、F_Orgと呼ばれる列を使用することです。これは、会社では4桁より大きくなります。これはすべてスクリプトによって処理されます。
データベース設計の回答でよく触れるトピックの1つは、(a)リレーショナルデータベースの技術的な側面(たとえば、テーブルや列の宣言など)を考える前に、まず(b)を強くお勧めします。関心のあるビジネスコンテキストのすべての特性を正確に定義します。これは、エンティティタイプ、そのプロパティ、およびエンティティ間に存在するすべての重要な関連付けを識別することを意味します。
上記の要素に関する定義のグループは、一般にビジネスルールと呼ばれ、適用可能な概念モデルを構成します。
また、(1)データ管理と(2)リレーショナルデザインと操作については、(3)質問やコメントで取り上げたいくつかの側面を明確にするのに役立つ可能性がある他の重要なテーマがあると思います。答えが進むにつれ、これらすべてのポイントを統合します。
抽象化の関連する概念レベルの再評価を始めましょう。この点で、ビジネス環境を説明する一連のステートメントを作成することが重要です。したがって、特定のケースでは、ビジネスルールを意図的にできるだけシンプルに保つ必要があります。
説明的なIDEF1Xモデル
次に、上記で定式化されたビジネスルールに基づいて、意図的に比較的単純なIDEF1Xを作成できます。a図1 に示すようなモデルを使用して、重要な機能のほとんどを単一のリソースに統合するグラフィカルデバイスを作成します。
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つは、エンティティタイプCompany
とPerson
の間に多対多(M:N)の関連付けまたは関係があることを示しています。これにより、CompanyOwner
( CompanyShareHolder
と呼ばれるか、ビジネスドメインで使用される用語をより適切に表すものとなるでしょう)。
現在のモデリング演習で特に重要な特性の1つは、StockShareQuantity
関連付けのコンテキストでのみ発生するため、CompanyOwner
という名前のプロパティです([Sharesの合計を表す))。このように、それはPerson
にもCompany
にも属していませんが、これら2つの別個のエンティティタイプ間で発生する可能性のある接続に属しています。
指定したとおり、各CompanyOwner
オカレンスまたはインスタンスは、そのCompanyId
値とOwnerId
値の組み合わせによって識別されるため、これらのプロパティはエンティティタイプの図で複合PKとして強調表示されます。 CompanyOwner.CompanyId
プロパティはCompany.CompanyId
を指すFKで区別され、CompanyOwner.OwnerId
はPerson.PersonId
を参照するFKで示されます。
少し複雑なPerson
エンティティタイプを描くことを目指して、Person.Name
をFirstName
とLastName
に分解し、列GenderCode
、BirthDate
、BirthPlace
を含めました。これらのすべてのプロパティを組み合わせた値は、通常、特定のビジネスシナリオでPerson
を識別するために使用されますが、Person.FullName
を追跡することで、データ使用の要件を満たすことができます。議論中の特定のデータベースに関して同じアプローチに従う必要はありません。
その後、データベース管理システムが提供するデータ定義言語(この場合は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 (これは、ダイアグラムに描かれているものと非常に似ていますが、いくつかの重要な違いがあります):
bdb <> fiddle と SQL 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回表示されます。私の最初の質問は、これをどのように設計するかでした。私は自分の最後の手段になると思う各会社のテーブルを作ることを考えましたが、これを行う方法に関する他のガイダンスやヒントはまだありません。
No、notそれぞれに対してテーブルを作成するCompanyこれは最適ではないためです。
その点で、以前に提示された各ベーステーブルに保持されているすべての行は、特定のタイプに属する特定の概念レベルのエンティティ、つまり次のいずれかについてassertionであると言えます。 CompanyまたはPersonまたはa CompanyOwner。
したがって、指定されたCompanyに関する行はCompany
テーブルに保持されますonly onceと指定されたPersonに関する行は維持されます一度だけPerson
テーブル内。次に、Personはゼロ、1つ以上のCompaniesを所有できるため、各行はPersonが個人に対して持つ正確な接続に関するものですCompanyはCompanyOwner
テーブルで囲まれています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');
その後、たとえば、すべてのCompaniesのOwnersに関するデータを含むテーブルを作成する場合は、次のように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桁より大きくなります。これはすべてスクリプトによって処理されます。
CompanyのAddress(es)およびPhone Number(s)がアプリケーションプログラムコンポーネントに格納されていることを意味するかどうかはわかりません(おそらく、レコードとフィールドを含むファイル、または類似のもの)が、実際にその情報を処理している場合は、ジョブに適切なツールを使用する必要があります。つまり、データベース構造にこれらの側面を含め、データベース管理システム(PostgreSQLなど)によって提供される手段。これにより、関係データを最適な方法で管理できます(たとえば、物理レベルでサポートされる、リレーショナル代数と宣言制約に基づく論理レベルの操作により)強力なセット処理エンジンによる)。
スーパータイプとサブタイプの関係を表す実現可能なDDL構造拡張
したがって、あなたがそれを決定した場合、あなたのビジネスドメインで
そして
this answer に含まれている図を分析して、検討中のシナリオと非常に似ているシナリオについての質問を探したいと思うかもしれません(他の機能の中でも特にパーティー組織または人物サブタイプを表すスーパータイプ、人役割の再生所有者Organizations、およびAddressesおよびPhoneNumbersOrganizationsおよびPeopleとリンク=スーパータイプを介して)、一時的な拡張機能の参照として使用できるため。