2015 03 23

階層問い合わせで順序を作る

バスの窓からぼんやり外を眺めていて、ふと目を惹かれたのが 「みなごろし部屋」 という広告。 えっ? と、ちょっと吃驚して見直したら 「まごころ部屋探し」 だった。 これは似てるのか?

さて、こちらは間違いなく皆殺しの話。 殺されたのは人ではなく猫だけど。 毎日新聞から。

千葉県船橋市の県立高校で、30代の男性教諭が生まれたばかりの子猫5匹を学校の敷地に埋めていたことが県教委への取材で分かった。 教諭は生徒に穴を掘らせるなどしていた。 少なくとも4匹は生きていたといい、県警は動物愛護法違反の疑いで調べている。

県教委によると、教諭は今月6日、学校敷地内で野良猫が産み落としたとみられる5匹を発見。 同日の放課後、担任を務めるクラスの複数の男子生徒に目的を伝えず、穴を掘ることなどを手伝わせた後、1人で猫を埋めた。 教諭は 「どう対処すればいいのか分からなかった。 いずれ死んでしまうだろうと思った」 と説明しているという。 9日に保護者から学校に連絡があり、10日に教諭に事情を聴いた。 学校は24日に臨時の保護者会を開いて経緯を説明する予定。

記事中の教諭の言葉 どう対処すればいいのか分からなかった は、苦し紛れの嘘だよな。 楽しかったのか、殺してみたかったのか、殺意はちゃんとあったのだ。 その気持ちを素直に言うともっと非難されることはわかるが、人に説明して納得してもらえそうな言い訳が思いつかなかったというだけの話だろう。 自分でも理解不能な衝動だったのかもしれないが。

これ、NHKのニュースでもやってて、学校の関係者が 「命の大切さを教えるべき立場なのに…」 なんて言ってた。

命の大切さ云々はただの定型句で特に深い意味はないんだろうが、その場にいた記者にはせっかくだから突っ込んでほしかったな。 命の大切さを教えるべき立場なら、子猫をどうすべきだったのか? と。 この流れで、まさか保健所とは言わないだろうし、かといって具体的なことは何も考えてないだろうし、ちょっと突っ込んで質問すれば、その人も 「どう対処すればいいのかなんて分りません!」 と逆切れする面白い展開になったかもしれないのに。

「みんなで子猫を飼って、十分に愛着が湧いたところで保健所に送り、みんなで保健所に行って殺処分されるところを見学して、命の大切さとそれを奪われる辛さを教えます」 なんて言ったら、ちょっと学校ってものを見直すかも。

階層問い合わせで順序を作る

最近のことだが、SQLを書く中で

0, 1, 2, … 9, A, B, C, … Z

という順序が必要な場面があった。 この順序をどう作るかという話。

最初に思いついたのは、1文字づつのselectをunionで36個もずらずら並べること。

select idx from ( select '0' idx from dual union select '1' idx from dual union 〜 select 'Z' idx from dual )

なんの工夫も無いし、はっきり言ってかっこ悪い。 無理矢理良い点を挙げるなら、何をしたいのかがすぐに分かることか。

次に思いついたのが、この順序だけを持つテーブルを予め作っておくこと。 きっと他でも使うし、特定の範囲を取り出すときにテーブルとして独立していると便利だし、なんて言い訳とセットで思いついた。 が、他でも汎用的に使うなら、数字が0〜9だけってのが中途半端で、この案も微妙なことに。

値を固定して持たせるから、どこまで持つかで悩むのだ。 だったら固定しなければ良いのではないか。 例えば、順序用のテーブルを中間テーブルとして用意し、値は必要に応じて都度登録するとか…

と、ここまで考えたところで迷走の気配に気付いて、一旦中断。 こんな場合に世間ではどうしているのかをgoogleで調べたところ、数字だけの場合だが、階層問い合わせを使う例が見つかった。

1〜9が欲しい場合は、次のSQLで取得できる。

select level lv from dual connect by level < 10

階層問い合わせは知っていたけど、こんな使い方があるってのは目から鱗が落ちる思いだったよ。 俺が知らなかっただけで、定番の使い方だったりするのかな。

これを応用すれば、元々の要求も簡単に実装できる。 こんな感じ。

select to_char( level - 1 ) lv from dual connect by level <= 10 union select chr( ascii( 'A' ) + level - 1 ) lv from dual connect by level <= 26

最初のselectが0〜9。 levelは1から始まるので、1引いて文字に変換している。

次のselectがA〜Z。 A〜Zは文字コードでも連続していることを前提に、Aを文字コードに変換し、それにlevelを足し、再度文字に変換している。

階層問い合わせに馴染みが無いと、何をやっているのかをパッと見てすぐには把握できないけど、応用範囲の広さと記述量の少なさは圧倒的。 そもそもデメリットが無知によるものだし、馴染みが無いとか言ってないで馴染めば良いんだよな。 よし、馴染む。 もっと便利な使い方がありそうだし、ここで改めて階層問い合わせについて調べてみよう。