ABDをまた考える

やっぱりこれはDB設計の技とだけ考えると痛い目に会うと思いますよ。

資料にあった売上のER図、あそこから請求金額を取得しようと思ったんですよ。ある請求期間内の売上金額を顧客単位で集計する訳です。

SQLはこうですかね。資料がない方はあいすみません。

SELECT
    関連.顧客ID,
    SUM(明細.数量 * 商品.単価)
FROM
    売上_関連 関連
    INNER JOIN
    売上
    ON 関連.売上ID = 売上.売上ID
    INNER JOIN
    売上明細 明細
    ON 関連.売上明細ID = 明細.売上明細ID
    INNER JOIN
    商品
    ON 関連.商品ID = 商品.商品ID
WHERE
    売上.日付 BETWEEN 請求期間FROM AND 請求期間TO
GROUP BY
    関連.顧客ID

あっなんか凄い簡単だ。

いや、そうじゃないんだ。あぶないあぶない。あやうくコロっと落とされる所だった。

例だと簡単過ぎちゃうので、消費税金額を売上テーブルに持つとしましょうよ。売上計上時に仮受消費税は認識されるの法則に乗っ取りまして。で、取引はBtoCなので総額表示には準じない、よって明細単位でなく売上テーブルに消費税金額を持つ。

よって今の所、売上テーブルには

  • 売上ID
  • 日付
  • 消費税金額

の3つのカラムがあるとします。

さて、消費税金額も請求金額に含めないといけませんので、SQLはこうしないと上手い事取ってこれないんじゃないかな。

SELECT
    請求.顧客ID,
    SUM(請求.請求金額)
FROM
    (
    SELECT
        関連.顧客ID,
        関連.売上ID,
        売上.消費税金額 + 
            SUM(明細.数量 * 商品.単価) AS 請求金額
    FROM
        売上_関連 関連
        INNER JOIN
        売上
        ON 関連.売上ID = 売上.売上ID
        INNER JOIN
        売上明細 明細
        ON 関連.売上明細ID = 明細.売上明細ID
        INNER JOIN
        商品
        ON 関連.商品ID = 商品.商品ID
    WHERE
        売上.日付 BETWEEN 請求期間FROM AND 請求期間TO
    GROUP BY
        関連.顧客ID,
        関連.売上ID,
        売上.消費税金額
    )請求
GROUP BY
    請求.顧客ID

前のSQLみたくして取って来たら、消費税金額が明細の数だけ膨れちゃいますね。

えー、つまり、このSQLを書くためには、売上と売上明細の親子関連の構成について知っていなければならない訳です。

それが、ABD的な売上_関連テーブルからは読み取れないのです。

一般的なER図では、FKとリレーションシップのあり方から親子関係を見て取る事が出来ます。とは云え、ABDの前段階で主キーはすべからく機械的にIDにせよ、ってのがありますんでその時点で親子なんだかただの参照関連なんだか素直に見て取れなくなりますが、それでもFKにユニーク制約を付ける事でまあ判るかなあと。

じゃあABDの場合何処で親子関連構成である事を知るんだろう。

まあ売上と売上明細じゃ名前で明白なんですけど、そこは、どうかひとつ!バカのふりを御願いします。

ここで「データモデル = ビジネスモデリング?ちゃんちゃらおかしいぜ」と云う言葉が蘇ります。ABDはプロセスに注目してる訳で、データモデルから「えー業務上このデータとこのデータはこういう構成で〜」とかのビジネスモデリングを導き出すのはダメなのだと、あの煽りはABDへの大いなる伏線であったのかと、思った訳です。

主キーはIDとかm:mにしておけとかも全部伏線。

じゃあどこから見出し明細構成を読み取るのよ、と云うと、ここで今度は「DB設計はUIから!モデリング幻想は捨てること!」と云う言葉が蘇って来ましたよ。

そうか、画面と帳票から読み取るのが正しいって事か、と。だからちゃんとUIを気合入れて決める必要があって、しかも業務のあり方がすっと入ってくるようなUIにするべきかと。

なんだ、突っつこうと思ったら自己レスで終わってしまった。いやー難しいよなあ。

ここで1行目の、やっぱりこれはDB設計の技とだけ考えると痛い目に会うと思いますよ、に戻る。業務フロー即ちアクティビティをしっかりと定義して、それに沿ってUIをばっちり決めて、そこから始めないといかんのですね。そうじゃないとさっきみたく「さーて請求登録のSQLでも書こうかな〜」とか云う時に、消費税金額が本来の数十倍の請求金額を取得しちゃったりとか起きかねない。

うーむ。安易にまねっこしてはいけませんね。開発プロセス全体で考えないといけない。