SQLと私
これはウイングアーク Agile and DevOps Transformation Stories のAdvent Calendar 2022、2022年12月14日の投稿です。
はじめに
こんにちは!ウイングアーク1stの木村です。
私は「Dr.Sum」というデータ分析用の集計エンジンの品質担当をしております。
私が入社した10数年前は「Dr.Sumはデータベースライクな集計エンジン」という宣伝文句でした。
最近はSQL構文が拡張し、連携するBI製品も増えて汎用的な「データベース製品」として日々発展し続けております。
他社では中々経験できない「データベース開発」に携わることができて充実感を味わっています。
私はデータベース技術の中でも特にSQLが好きです。
今回は「なぜ私がSQLにハマったか」を書きたいと思います。
若いときの苦い経験
前職で小さい受注管理システムを設計・開発・保守を一人でやっていたときの話です。
「売上未計上チェックリスト」という帳票のニーズがありました。
ER図を眺めながら「受注テーブルの売上計上区分が”未”のレコードを抽出すればいいな」と安易につくりリリースしました。
しかしユーザーからチェックリストに出力されないデータがあると指摘を受けました。
「見積だけして受注をスキップするフローもある」
「売上が立っても取消されたら未計上として表示してほしい」
私の考慮不足でした。
正直テーブル設計からやり直したい気持ちにもなりましたが、いろいろ検討した結果、各テーブルのレコードの存否で解決する方法があるとわかりました。
「見積はあるけど売上がない」または「受注はあるけど売上がない」一覧を抽出すればいい。
当時の私はCOBOL脳でしたので、ぐるぐるループさせて中間ファイルへ書き込みたい派でした。
でも開発ツールの事情でSQL一発で解く必要がありました。
そもそもSQL一発で解けるのかな・・・。
SQL
悶絶した結果、下記のイメージのSQLで解けました。
SELECT MAX(SQ.見積番号),MAX(SQ.受注番号),SQ.顧客名
FROM (
SELECT 見積.見積番号 AS 見積番号,0 AS 受注番号,見積.顧客名 AS 顧客名
FROM 見積
LEFT OUTER JOIN (SELECT 見積番号 FROM 売上 WHERE 削除区分 = 0) AS 売上
ON 見積.見積番号 = 売上.見積番号
WHERE 売上.見積番号 IS NULL
UNION ALL
SELECT 0 AS 見積番号,受注.受注番号 AS 受注番号,受注.顧客名 AS 顧客名
FROM 受注
LEFT OUTER JOIN (SELECT 受注番号 FROM 売上 WHERE 削除区分 = 0) 売上
ON 受注.受注番号 = 売上.受注番号
WHERE 売上.受注番号 IS NULL) AS SQ
GROUP BY SQ.顧客名;
このSQLを実行して期待通りの結果を得たとき、
業務要件とデータモデルとSQLが一気通貫でつながった感覚がありました。
そして外部結合やUNIONの使い道が腹落ちした瞬間でもありました。
以降私はSQLの奥深さに魅了され、現在のDr.Sumというデータベース製品開発に従事するところに至ります。
まとめ
はじめてSQLを見る人にとっては、他の開発言語と比べて変数定義もループの記述もないのでわかりずらい言語かと思います。
まずはデータベースがSQLを解析する順番、
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
を覚えるだけできっと理解が深まると思います。
あまりにも複雑な要件のときは、処理速度や保守性の面からも手続き型で解決した方がいい場合もあります。SQL一発で結果を得ることに固執しないでくださいね。
最後まで読んでいただき、誠にありがとうございました!