web-dev-qa-db-ja.com

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

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

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

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

21
kmote

@Todd Everettの答えを読んだ後、解決策が思いついたので、先に進んで自分の質問に答えます。私がやろうとしていることは、ColumnUnitsSchemaTableColumn(UnitsIDは別のUnitsIDテーブルへのFK)の4つの列を持つ別のUnitsOfMeasureテーブルを作成することです。測定。明らかに、このアイデアの最大の欠点は、開発者が列またはテーブルの名前を変更するたびにこのテーブルを編集することを忘れないようにする必要があることです(おそらく DDLトリガー]、それ以外の場合、システムはbreakします。しかし、そのような名前変更がまれであり、開発ショップが小さい(私の場合は1人だけ)と仮定すると、このアーキテクチャは機能するはずです。利点は、現在のDBに侵襲的な変更を加える必要がなく、元の投稿の2番目のオプションで必要な行ごとに1回ではなく、列ごとに1回だけ値を格納する必要があることです。

3
kmote

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

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 to UOM、および計算ステップです。

それは私の2セントの価値があります。現在のデザインで再起動する機会があったら、これらの参考資料を参考にしてください。

12
Todd Everett

すべての仕事。

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

また、変換は安全性が高くなく、丸め誤差やオーバーフローなどの影響を受けやすいことにも注意してください。

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

拡張プロパティの場合、それはドキュメンテーションにのみ有効です。適切な列名はドキュメンテーションに適しています。名前で固定単位であると暗黙に示されている列の問題は、測定単位を変更すると、最終的に隅に追いやられることです。新しいクライアントは、ガロンではなくバレル単位でオイルを必要としています。データが含まれているため、問題ありません。独自のデータベースですが、列名は誤解を招くようになりました。

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

8
Cade Roux

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

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

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

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

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

7
dodgy_coder

次の式を使用すると、任意の単位を同じタイプの別の単位に変換できます。

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ユニットを交換するだけで、逆演算を挿入します。

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

5
peroyhav