はじめに
SQLコンテストという、1時間以内にSQL(SQLite3)に関する問題を4問回答して速さを競うコンテストについて、全問正解できたので勝手に解説します。
直近で行われたのは4/19〜4/22の第12回です。これから取り組む人はネタバレ注意です。
筆者スペック
IT系?勤務5年目。データサイエンス系業務(が長め)(最近は意味不明な業務)
SQL実務4年間くらい(ユーザ側でSELECT文メイン)。AP/DB持ち
解説
問題1
部門テーブル(DEPARTMENT)に、以下の内容で2件のデータを挿入しなさい。(以下略)
INSERT
文の問題でした。
私は業務上INSERT
文をほぼ使わないので、構文を調べるところから始めました(ロスタイム)が、、構文コピペで解答できました。
ちなみにSQLコンテストはSELECT
文では難しい問題が出ますが、INSERT/UPDATE/DELETE
は簡単な内容が多い気がします。
(お試しの画面で結果が確認しにくい&普通INSERT系は表計算ソフトで確認しながら投入していくと思うので、当然といえば当然ですが・・・)
問2
社員テーブル(EMP)に登録されている、各社員の社員英字名(EMP_ENG_NAME)の先頭から10文字を表示しなさい。ただし、半角スペースは文字数にはカウントしないで取り除いて表示すること。また、社員英字名が未入力(NULL)の場合は、CUTOUT_STRに'未入力'と表示すること。(以下略)
文字列を操作してSELECT
しなさいという問題でした。
要件を読むのが面倒くさいのですが、substr()
やreplace()
などの関数を使えれば比較的シンプルにできました。
SQLは言語によって細かい動作が若干違ったりしますが(show tables
と\dv
みたいな)、文字列操作は大体同じなので、そこそこ短時間で解ける気がします。
問3
2024年4月1日時点の商品テーブル(ITEM)と2023年12月31日に商品テーブルをコピーして作成した商品履歴テーブル(ITEM_HISTORY)がある。
この2つのテーブルを比較して、2023年12月31日から2024年4月1日の期間に、追加、更新、削除されたデータを表示しなさい。(以下略)
SELECT
とJOIN
の問題でした。
多くの回答者はLEFT OUTER JOIN
して、追加のテーブル・更新のテーブル・削除のテーブルを3つ作っていたのですが、私はFULL OUTER JOIN
でくっつけて1度で処理していました。
私は、複数テーブルを紐づける際、気軽にFULL OUTER JOIN
を使うのですが、業務的によく使っていたから経験あり&考えるのに慣れているだけで、普通はLEFT OUTER JOIN
を複数回やったほうが将来的な保守性の面では良さそう・・・と思いました。
個人的には良問だと思っています。テーブルをゴチャゴチャ紐づけていって色々なテーブルから情報を取るのがSQLだと思っているので。。
問4
売上テーブル(SALES)より、2024年3月1日から28日までの4週間分のデータを集計し、売上件数と売上金額合計(SALES_AMT)の一日当たりの平均値を曜日別に表示しなさい。(中略)金額は3桁ごとにカンマを入れ、最後に'円'を付けること。(以下略)
SQLコンテストにまれによくある、SQLで文字列の表示形式をゴリゴリ変えさせる問題でした。
表示形式は別言語、どちらかというとUIに近い側で操作した方が良いとは思いますが、SQLiteで何とかするという縛りプレイだと思い、心を無にして取り組んでいます
SQLiteだと表示形式はprintf()
で色々カスタマイズできる模様ですが、CASE文を用いて手動でカンマを入れる回答が多かったです。
私は「対象期間3/1〜3/28のうち、データがない日があると変なことになりそう」と思い込んで、WITH RECURSIVE
構文を使って最初に日付のリストを作ったりしていましたが、模範回答を見ると不要そうでした。(ロスタイム)
完走した感想
問題4はめんどくさかったものの、全体的に簡単だった気がします。実際、満点回答者が結構いました。
私は金曜日の仕事終わりに取り組んだのですが、4位(42:41)と最高順位でした。。
ブドウ糖がキマったのかな(?)
(下書きにあるのを忘れていて上げるの遅くなりました、、)