複数のサービス/ユーティリティを同じ請求書で請求する請求システムの倉庫を構築しています。そのため、認識されている倉庫の設計方法に準拠するのに本当に問題があります。私はまだOLTP帽子をかぶっています。
例として、電気、ガス、携帯電話の料金を含む単一の請求書を作成できます。
法案の3つのコンポーネントすべてに、固定料金と使用量ベースの料金という2つのコンポーネントがあります。携帯電話に単純化しても、ビジネスに必要な詳細レベルを格納することは、2つのファクトテーブルが必要であることを意味します。
FactMobileFixedCharge
FactMobileCalls
これらはそれぞれ1つの請求書に送られます。これに加えて、請求書レベルでのトランザクションもあるため、さらにファクトテーブルが必要になります。
FactInvoiceTransaction
この単純な例の基本的なスキーマは次のとおりです。
私が行ったすべての読み取りは、InvoiceLineItem
の例に取り組み、ファクトとディメンションのように見える請求書の問題を解決します。ここで、請求書のファクトは基本的に子テーブルに伝達され、冗長性をもたらしますが、標準的な練習。
本番請求システム自体には、請求書に表示されるアイテムを含む15のテーブル、請求書レベルの料金とカテゴリ別の15のテーブルの料金の概要を含む概要テーブル、および請求書テーブル自体があります。
私のシナリオはこれに一致するとは思いません。請求書には、報告する必要のあるさまざまなものが含まれているためです(請求先住所、請求書のマーケティング資料、支払い方法、請求書の形式、電子メール、オンラインまたは紙の請求、繰越残高、最後の請求書以降の支払いなど)。 1つまたは2つのテーブルがある場合、これは許容できる冗長性ですが、15のファクトテーブルでは多くのように見えます。
複数のテーブルがある場合に多くの冗長性があることに加えて、同じ請求書のレコードを取得するためにFactMobileCall
とFactMobileCharge
をリンクする必要があります。また、縮退を許しません。ディメンションは2つをリンクするための良い方法です。
基本的に、これはすべてInvoice
がディメンションであることを示しています。特に、請求書レベルには測定がないため、インポートごとに新しいレコードが存在するだけなので、それは事実であるように思われます。
これは私の質問につながります:
InvoiceLineItem
の例が実際には適合しないように見える状況に遭遇した唯一の人であるとは信じられません。これに対処する認識された方法はありますか?詳細については、私のウェアハウススキーマは現在次のようになっています(ここでは、Invoiceがディメンションのような事実であることを認めています)。
これは私が自分でそれに取り組む方法です。ファクトを「アクション」または「動詞」と見なし、ディメンションをファクトの記述子と見なすことを忘れないでください。
したがって、請求書と請求書の項目はどちらも事実です。これに対処するための1つのアプローチは、ファクトテーブルを請求書レベルのラインアイテムの粒度に合わせて作成したことです。これは、あなたが述べたような特定の事柄の冗長性につながります。これは、請求先住所のディメンションや、税金などの特定の請求書レベルの事実に問題がない場合でも、明細レベルの項目に分類でき、請求書レベルの金額まで集計できます。
うまく分解できない請求書レベルの事実がある場合、このアプローチは失敗する可能性があります。たとえば、顧客は複数の支払い方法を持つことができますか?請求書に複数の種類のマーケティング資料を添付できますか?マーケティング資料は特定の項目に関連していますか?
これらの質問をすると、間違いなくFactInvoiceLineItem、FactInvoice、FactPaymentsなどの複数のファクトを作成し、最終的に請求書番号などと結び付けてしまう可能性があります。これにより、特定の事実をより適切に分析できるようになります。
この方法でファクトテーブルからキューブを構築する場合は、ビューを使用してキューブを読み込むことをお勧めします。このようにして、さまざまなファクトテーブルに加わった請求書の高レベルのビューを取得し、ラインアイテムの数、支払いの数などの測定を行うことができます。
とにかく、私はそのルートをたどることは、同じ粒度を持つファクトテーブルを分割するよりもはるかに優れていると信じています。
ハッシュ化についてさらにサポートが必要な場合は、詳細を記載してお気軽にご連絡ください。
2層のファクトテーブルは、通常、その価値よりも問題が多くなります。それはあなたのOLTP蹴りを正規化する本能です-戦いましょう!倉庫/スタースキーマパラダイムを理解するのに数か月かかりました。
これらすべての請求書ヘッダー情報は、いくつかの追加のディメンションに組み込むことができます。これにより、いくつかのINT
列がファクトテーブルに追加されるだけなので、必要な余分なスペースが(必要な場合)最小限に抑えられます。これらのディメンションテーブルには個別のデータセットのみが含まれるため、実際には冗長性はほとんどありません。
あなたの説明に基づいて、私はこれから始めます:
Invoices
Accounts
へのFK)MarketingMaterial
へのFK)Products
へのFK)Dates
へのFK)Dates
へのFK)Payments
Accounts
へのFK)PaymentMethods
へのFK)Dates
へのFK)Accounts
これはタイプ2のSCDであるため、各ファクトレコードに格納される情報(アドレスなど)は、その時点でファイルにある情報を反映しています。
Products
外部キーを強制するのではなく、純粋に論理的にします。 ETLがタイトであれば、オーバーヘッドは不要です。
データベースでPaymentMethods
が何を伴うのかわかりません。それが単に「小切手、カード/デビットカードを使用したのか、それとも請求調整なのか」の場合。 Payments
でその退化した次元を作成できます。カード番号や有効期限などのフィールドがある場合は、ファクトテーブルを読み込まないようにディメンションにする必要があります。
BillingAddress
とServiceAddress
を区別したい場合があります。 Accounts
テーブルに2つのアドレスフィールドセットを作成するか、Hiveアドレスを新しいテーブルにして、ファクトテーブルの両方を参照させることができます。他のすべてが等しいので、私は最初に傾けます-それはファクトテーブルを可能な限り狭く保ちます。
トリッキーな部分は、Invoices
をPayments
に接続することです。これは多対多の関係であり、倉庫では痛みを伴う傾向があります。多くの場合、必要はありません。特定の時点でInvoices
とPayments
をAccountNumber
で集計し、残高を報告するだけです(これを毎月のスナップショットテーブルに保存できます)。ただし、ビジネスユーザーはおそらく、より正確なブレイクアウトを望んでいるでしょう。テーブルは非常に単純です。
PaymentAllocation
...しかし、各支払いからいくつのドルを各請求書項目に送るべきかを決定することはめったにありません。まだ全額が支払われていない最も古い請求書項目に収益を割り当てますか?それが始まりです。
同様のアプローチは、コストを収益に、またはその逆に割り当てて、きめの細かい利益を計算するために機能します。これは大変な作業ですが、最終的には、どの顧客や製品が実際にビジネスを推進しているかを計算できます。
今後のステップは、単一のアドレスのアカウントをグループ化するHouseholds
テーブルを作成することでしょう。