[DBデザイン#26] 素なデータを見つける:データをどう見るのか

前回は、データベースの基本的な考え方として、もとになる集合があって、そのどれかの要素が1つだけフィールドになるという「ドメイン」の考え方を紹介しました。そのフィールドが集まって表を形成しますが、それを「リレーション」と呼ぶというのが定義です。表そのものや、フィールドという構造がある、レコードという繰り返しがあるという諸々を含めた意味が込められている用語になります。ただ、現場的には「関係性」のこともリレーションと言ってしまうことがあり、ちょっと混乱します。本来は「リレーションシップ」なのでしょうけど、リレーションと言ってしまって通じるところもあって、自分でも時々混乱している時があり、反省する次第です。

さて、フィールドに入れるべきデータの集合そのものがどういう成り立ちをしているのかをさらに探りましょう。都道府県のように、ほぼ誰が見ても明確なドメインはありますが、実際の業務で出てくるデータには、元の集合が書ききれないもの、定義が揺らぐもの、同じものなのに同一名称など、かなり多種多様なものがあって捉えどころがないという考えになるかもしれません。あるいは、「数字」と「文字列」が一般的な言い方でしょう? という言い方もできるのですが、そうすると、なんでもありということになり、ドメインの考え方が揺らぎます。

実際にデータベースに入っているデータを仔細に見ると、結局のところ、「つけた名前」であるものと「測定値」なのではないかということを考えました。「つけた名前」はここでは「ラベル」と呼びます。英語のlabelに「名前を付ける」という意味があるからですが、「ラベル」というより発音に近いのは「レーベル」でしょうけど、日本語として通用している「ラベル」で以下は表現します。

例えば、「埼玉県」というのは、3文字の文字列ですが、この文字列そのものが、都道府県単位の1つの行政区域を示しており(法律的にはもっと細かくあるのでしょうけど)、ある意味、広い土地全体に対して名前をつけたものです。そして、日本国内は、都道府県で地域を区別できるとか、ある一地点はどれか1つの都道府県であるのかということが通常は結論づけられるなど、素なデータであることが誰が見ても意見の相違がないようなラベルなのです。47都道府県はいずれも文字列という見方もできるのですが、47種類のラベルがあるというのがさらに抽象的な見方になります。そのラベルに書いてある名前があるドメインでは「埼玉県」であるとなっているものの、ドメインが微妙に異なる、つまり状況が変われば「Saitama Pref.」となっているのかもしれません。

このように、データはラベルではないかと考えると、現実にデータベースに保存しているデータのほとんどはラベルです。文字列で記述すると、人間が普段のコミュニケーションで利用している言語に登場する形態と同一と見做せる記述が可能なので、文字列で記述することが多いでしょう。しかも、厳密にはなんらかの定義がきちんとされた上で、ラベルの集合があって、その中の1要素がフィールドに収められています。名前も、姓や名に記述される文字列は、いずれもラベルです。そう考えると、ほぼ全てのデータは、誰かがそれに対してつけた名前や、あるいは番号であって、それらのデータの成立過程を考えれば、フィールドの元になる集合というものの存在が明らかになります。商品の表にある商品名は、やはりラベルです。会社で扱っているさまざまな商品には、通常は製造した会社が付けた名前がありますが、基本的にはそれは他の商品と別の商品であって区別ができるように付けた名前、すなわちラベルなのです。「SK-110B」のような実利、すなわち商品名から商品の属性や成り立ちを示唆するような情報を込めたような実利を追求したような商品名もあれば、「ラッキースタンプ」のようなマーケティングの効果を高める意図が込められた商品名もあるでしょうけど、いずれも、ラベルであることには変わりありません。そうしたラベルを記録するのに文字列という表現形態は非常に便利であり、ほぼあらゆる形式のラベルに対応できるので、データベースとして文字列記録機能が実装されているということになります。ですが、フィールドには文字列を記録するのではなく、設計の上では、ラベルが記録されるという考え方が重要なのです。

ただ、データベースの中身には、ラベルでないものも存在します。例えば、体重や温度といった「測定値」です。測定値とは、なんらかの単位をもとにして測定した値です。これはラベルとは言い難いものです。もっとも、群論の考え方からすると、整数や有理数などは要素が無限の集合の要素ということにもなるので、結局はラベルではないかと考えられるのですが、データの成り立ちが違うと考えています。ラベルと測定値は、照合に意味があるかどうかの違いがあると考えられます。ラベルはなんらかの方法で、同一と見做せるものは同一です。つまり、ラベルとしての文字列が同一であれば、それらデータが示す現実のものは、そのラベルの定義範囲(ドメインの定義と同義)において一定であるということになります。ある会社に売った商品Aと、別の会社に売った商品Aは、同一の商品名なので、商品という区分においては同一です。ここでの同一は、以前に記載した「ある会社の営業部における商品の考え方」に基づく判定になりなす。箱が異なり、製造番号が違うなどの物理的な違いはあるかもしれませんが、「商品」というドメインでは同一と見做すということが営業部においては行っていることです。これが照合の意味するところです。ところが、測定値は同一の測定値は、それは偶然そうなっているかもしれません。正しく定義されたドメインではラベルは同一であることを保証できます。いや、むしろ、それがドメインの集合で検討した場合の定義そのものでもあります。「正しい定義」に「ラベルは重複がない」などのルールを入れれば良いのですが、これは第二、第三正規形に繋がりそうなルールです。一方、2つの測定値は等しい値であることはあっても、それらは同一であるかどうかはわからないのです。極端かもしれませんが、測定値に対象と時間軸がぶら下がるとしたら、唯一無二の存在のように思えてくるのではないでしょうか。

ラベルと言えば文字列ということになりそうですが、一方、数値であってもラベル的な存在も扱うことがあります。ある出荷伝票があって、出荷済かどうかを0と1のどちらかで示す場合があります。良し悪しはともかくそういう実装は時々行われています。このとき0が未出荷で、1が出荷済みということはどこかにドキュメント化しないと、他の人には理解できないのですが、これもドメインの定義に当然ながら含まれていると考えます(実際、ドキュメント化されてないことがほとんどだったりしますけどね)。この場合、「0」と「1」は、測定値ではなくラベルです。便宜的に数値を割り振っています。ですが、これを「133」と「59887」の2つの整数を利用しても、ドメインとしては成立します。プログラムなどの記述が気持ち悪くはなりますが、割り当てるという意味ではなんでもいいとも言えます。ちなみに、0と1にしておくことで、プログラミング言語の論理型との変換がスムーズであることを利用して、コードの単純化をするのは基本テクニックですので、0/1の数値置き換えはエンジニアサイドでは当たり前のことでもあります。数値、特に整数は、同一かどうかの判定が非常に安定しています。文字列だと、全角と半角の問題など、ドメイン内では同一と見做せる文字列をコード体系の問題で異なる文字列で示すことができるので、もちろん正しく配慮すれば問題は発生しないのですが、そうした配慮が必要という点では安定性が整数に比べて減少するという考え方ができます。途中に出てきたIDの値を番号にすることが一般的ですが(最近はUUIDも使われますが)、その理由の1つはこうした照合判定の安定性があります。ちなみに、もう1つの大きな理由としては、照合のスピードが文字列よりも一般には早いということがあります。

いずれにしても、ラベルとなる数値は、一般には計算できません。1が出荷済みということで、1+1=2に何か意味があるかというと、2回出荷した? それはちょっと違いますね。出荷はするかしないかのどちらかです。「出荷済み+出荷済み」という演算はこのドメインでは定義されていません。よって、1+1という計算はできるのですが、その計算自体は意味がないのです。こうした数値を「名義尺度」と呼ばれます。

なお、数値には名義尺度以外に、「順序尺度」「間隔尺度」「比例尺度」といった区分があります。「順序尺度」はその大小が順序を決定することが可能なもので、例としては、アンケートでの5段階評価つまり、大変悪い・悪い・どちらでもない・良い・大変良い、に対して、1〜5の整数を割り振ったものです。ちなみに、こういうアンケートの数値の平均を出すのを平気でやる方も結構いらっしゃるようですが、基本は、それぞれの選択肢のヒストグラムを比較検討するのが基本です。どちらでもないと良いの差は1で、良いと大変良いの差も1ですが、本当にこれが等距離かどうかというのは通常は分かりません。なぜなら人間の感覚だからで、厳密で測ったものではないことが一般的で、個人差もあるからです。ただ、平均値同士の違いをざっくりと見るという点では若干意味があるのかもしれませんが、いずれにしても順序尺度であるということは忘れてはいけません。一方「間隔尺度」は数値の差が定量的に意味のある場合です。さらに数値としての0に意味がるような場合は「比例尺度」となります。名義尺度と順序尺度が「ラベル」で、間隔尺度と比例尺度は「測定値」であると言えそうですが、これについては反論が出そうな気もします。

ちなみに、商品IDなどのID番号は基本的には名義尺度です。ただ、システム自体が連番を振るような場合、順序尺度として利用可能ではありますが、これは副次的な作用であって、考え方は「区別する」ということが基本にあるので名義尺度になります。もちろん、ID番号は加算や減産はできたとしても結果に意味はないので、間隔尺度や比例尺度ではありません。ただ、順序尺度として使うには、番号の割り振り自体の管理が必要です。また、順序を変更することがIDの変更ということになり、これは別の回で説明する予定のキーフィールドは変更しない原則にも外れることになります。なので、通常は順序尺度とは考えません。順序をなんらかの方法で記録したい場合は、独立したフィルールドに数値を入れて管理をします。通常はUIとの連携にロジックが絡むことが多いでしょう。

いずれにしても、データベースにあるデータは、ラベルか測定値であり、業務システムではラベルの割合がかなり多くなります。そのような中でも確実に測定値なのは、単価、個数、金額といったあたりのフィールドです。いずれも0の基準は明確なので比例尺度と言えます。そして、金額が同じであれば、同一の販売であるかと考えるかというと、たまたま金額が同じだっただけかもしれないので、同一かどうかは分かりません。これが、測定値を照合には通常は使わないという実例です。

日付や時刻は実はラベルなのか、測定値なのはか難しいですが、差の演算が可能なことを考えれば間隔尺度なので、測定値であると言えます。しかし、年月日時分秒といったコンポーネントの集合のような考え方だと、ラベルのようにも見えます。例えば、年月だけを記録するような場合は、ラベル的な動きをするようなデータであることもあります。このように日付時刻は、単に記録することを超えるとかなり扱いが難しくなります。これも回を改めてですね。

データベースの中身に圧倒的に多い文字列は、ラベルです。つまり、誰かがつけた名前を使わせてもらっていて、それらが共通概念になっているということで、情報が伝達されているということです。ただ、文字列を記録しているだけではなく、ラベルを文字列として記録しているということに思いを巡らせれば、データベースの設計に必要な情報も浮かび上がるのではないかと思われます。

今回も図がないので、何か貼っておきます(笑)