データベースにユニットを保存する最良の方法


21

何かの量を表す数百の列を持つ大規模な(SQLServer)データベースを継承しました。これらの値の単位(「ガロン」、「インチ」など)は、拡張プロパティのMS_Descriptionフィールドに格納されます。この情報を保存するより良い方法があるかどうか疑問に思っています。ドキュメンテーションの目的には適していると思いますが、このデータに基づいて堅牢な単位変換計算を行うことは困難です。この時点で、私は侵襲的な変更を行う準備ができていませんが、そうする機会を得た場合、この点で推奨されるベストプラクティスは何ですか?私の頭の上のオプションには、次のものがあります。

  • 列名を含まれる単位に変更します(例: "TotalVolumeInGallons"。これにより、情報が少し入手しやすくなりますが、それでも私には弱いようです。)
  • すべての「金額」列に対応する個別の「単位」列を追加します(この列はnvarcharであるか、単位変換の計算を容易にする個別の単位テーブルへの外部キーである可能性があります。多くの列は、データベースのサイズをかなり2倍にする可能性があります-ひどく冗長なデータです。)
  • ユニット専用の拡張プロパティで新しいフィールドを作成します。(残念ながら、これがUnitsテーブルの外部キーになるとは思わない。)
  • 私が見落としている別のアイデアはありますか?

更新: @Todd Everettの答えを読んだ後、考えられる解決策が思いついたので、先に進んで自分の質問に答えます。(下記参照)


ベストプラクティスは、アプリケーション全体で単一の測定システムを普遍的かつ一貫して使用することです。SIが最適なシステムです。他のシステムの値は、ロード中またはプレゼンテーション層で変換され、各ユーザーが好みのセットを選択できます。
マイケルグリーン

回答:


12

あなたは何百もの列に言及しているので、EAVの設計を検討します。Joe Celkoがこれに対して警告している間、私はそれがあなたのユースケースに適用されるかもしれないと思います。すべての「金額」は数字であるように聞こえるので、Joeが説明するキャストの問題と、すべての「値」を文字列にする必要性を回避できます。すべての金額が整数の場合はさらに機能しますが、一部が小数の場合も機能します。測定単位を考えると、さらに一歩進んで、David Hayによるこの記事を基にした「ユニバーサルデータモデル」スタイルモデルを実装し、彼の著書「Data Model Patterns:Conventions of Thought」でも概説できます。。このモデルには、必要な場合にどの「量」をどの「もの」に適用するかを構成するという追加の利点があります。162ページの本に示されている追加のステップは、異なる測定単位間で変換するために使用できる測定単位変換テーブルです。以下に例を示します。

UOM Conversion              

UOM From    UOM To        Cal Step  Operator Factor Constant
Kilograms   Pounds        1         *        2.2
Celsius     Fahrenheit    1         *        1.8
Celsius     Fahrenheit    2         +               32

これは、KgからLbに変換するための最初のステップは、Kgに2.2を掛けることであると言います。変換に定数値も含める必要がある場合は定数もあり、複数のステップを作成する機能もあります。したがって、摂氏を華氏に変換する場合、摂氏に1.8を乗算してから32を加算します。キーはfrom UOM、to UOM、およびCalculation Stepです。

それは私の2セントの価値です。現在の設計で再起動する機会が得られた場合、これらの参考文献が参考になることを願っています。


とても興味深い食べ物を考えてくれてありがとう-私は多くを学びました。しかし、私の場合、EAVは適切なモデルではないと思います(提案を正しく理解している場合)。何百もの列がありますが、それらは決してまばらではないからです。ただし、このDIDは関連するアイデアを引き起こします(元の投稿のUPDATEを参照)。
kmote

あなたのアイデアは私にはかなりいいように聞こえます-あなたがすでに指摘したもの以外の問題について、私は手に負えないと思いません。しかし、列の名前を変更/変更できる場合、それはどの設計でも問題になります。これは、コラボレーションが楽しいときです-アイデアは、私たちのどちらも最初から考えていなかったように見えます!
トッドエベレット

8

すべて動作します。

2番目のケースでは、リンゴとオレンジを追加できないため、データが非常に簡単に誤解されやすいことに注意してください。

また、変換は非常に安全ではなく、丸めエラー、オーバーフローなどの影響を受けやすいことに注意してください。

さらに、比重や温度などの物理的な問題があります。20ガロンの水をポンドに変換するには、水の密度を知る必要があります。しかし、水の密度は温度によって変化するため、測定と同時に密度を知るか、温度を同様に知り、体積補正係数を使用する必要があります。

拡張プロパティの場合、それはドキュメント化にのみ適しています-適切な列名はドキュメント化に適しています。名前によって固定ユニットにあると暗示されている列の問題は、測定単位を変更するときに隅に自分を置くことになります-新しいクライアントはガロンではなくバレルのオイルを望んでいます-そしてそれは彼らのデータが独自のデータベースですが、列名が誤解を招くようになりました。

別のオプションは、元のさまざまな測定値に加えて、標準バージョンを固定単位(つまり、常にキログラムとメートル)で保存することです。固定ユニットでの集計操作は問題ないはずですが(たとえば、温度を追加しない場合を除く)、元の測定値は失われません。


1
あなたが言及する潜在的な「誤解」は、まさにこのデータベースの現在のアーキテクチャについて私が懸念していることの1つであり、私が減らす方法を考えていることです。
kmote

1
列名ソリューションの潜在的な欠点についての大きなポイント。
kmote

1
@kmoteこれは単純な問題ではありません-個々のトランザクションに元の測定単位が異なる可能性があるレポートがありますが、合計もあります-これはユーザーが選択した単位に変換した後の合計です。
ケードルー

7

過去に私にとってうまくいったシンプルなソリューションは、すべてのデータを「ベース」ユニットに保存することです。たとえば、長さの基本単位はミリメートルで、重量の基本単位はキログラムです。このソリューションでは、既存のデータの一部をベースユニットに変換する必要がある場合があります(まだ変換されていない場合)。

すべてのデータを標準のベースユニットに格納したら、ユニット自体をデータベース全体に格納する必要はありません。これは、システム全体の前提になっているためです。各ユニットタイプに必要な表示されたユニット(たとえば、mm、inches、cm、mの長さを表示するかどうか)は、アプリケーション/クライアントドメインの問題になり、ローカルストレージに保存できます。

新しい測定単位はほとんど変更されないため、サポートされているさまざまな単位間で変換するための単位変換テーブルは、アプリケーション内でハードコーディングできます。

別の問題に関連する解決策は、データベースにタイムスタンプを保存するときに、常に「ベース」ユニット-UTCに保存することです。

トピックに関する別の関連Q&A ...


5

次の式を使用すると、任意のユニットを同じタイプの別のユニットに変換できるため、

y = ((x + xOffset) * multiplicand / denominator) + yOffset

ユニットタイプとこれらの4つの値を含むテーブルを作成します。

From Unit     To Unit      Unit Type    From Offset    Multiplicand    Denominator    To Offset
'milligrams'  'grams'      'mass'       0              1               1000           0
'grams'      'kilograms'   'mass'       0              1               1000           0
'grams'      'ounces'      'mass'       0              100000          2835           0
'ounces'     'pound'       'mass'       0              1               16             0

変換する可能性のあるすべての測定値をリストのいずれかの側に追加した後、単にオフセットを否定し、被乗数と分母、およびToユニットとFromユニットを交換するだけで逆演算を挿入するクエリを実行します。

すべてのタイプの間に変換を追加するために、いくつかのフィルターとのクロス結合により、残りの変換を挿入できます。


3

@Todd Everettの回答を読んだ後、解決策が思いついたので、先に進んで自分の質問に答えます。私は私がやろうとしていると思うと、別の作成することでColumnUnits、4つの列で、テーブルを:SchemaTableColumnUnitsID(UnitsIDはFKが別々にある場合UnitsOfMeasure、テーブル)、これを測定のそれに関連するユニットに任意の列をマッピングします。明らかに、このアイデアの最大の欠点は、開発者が列またはテーブルの名前を変更するたびにこのテーブルを編集することを覚えておく必要があることです [ おそらくDDLトリガーを使用しますか?]、それ以外の場合、システムが壊れます。しかし、そのような名前の変更はまれであり、開発者は小規模(私の場合は1人だけ)であると仮定すると、このアーキテクチャは実行可能でなければなりません。利点は、現在のDBに侵襲的な変更を加える必要がなく、元の投稿の2番目のオプションで必要な行ごとに1回ではなく、列ごとに1回だけ値を保存する必要があることです。


面白いパズル...そしてあなたが持っている面白いアイデア。あなたのアイデアはクエリを簡単にしますが、あまり達成していないようです。参照データを別の場所に移動しました。何このデザインについて最も私を悩ます
サー誓う-ロット

...アイテムにさらに属性がある場合、さらに列を追加する必要があるということです。そのため、@ todd everettのeavデザインの提案が好きです。
サーズアロット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.