3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。(jehupc.exblog.jpから移転中)

(SQL)時間、分を別列に分けた仕様の時に、時間文字列を生成する方法

時間という情報を格納するのに datetime 型の時間の部分だけに入れることが多いかもしれませんが、24時を超えた時間を「25」という値で持ちたい時があるかもしれません。(まあ、datetime で日付を+1して保存するという方法もあるかもしれませんが。。)
というわけで、 "Hour"列と"Minute"列をint型で用意して、それに時間を保存するパターンについてのノウハウです。

DMBMSはSQL Server2005です。
この状態でSQLで時間を条件にしたい時、"Hour"列と"Minute"列を文字列(varchar)に直して比較したいわけですが、この文字列に直すというのが結構曲者でした。

普通に

SELECT 
STR( Hour , 2 ) + ':' + STR( Minute , 2) + ':00'

とすると、一桁の数値の場合
9:1:00
という風になってしまいます。

ということで、"Hour"列と"Minute"列の値が一桁の場合に0埋めするようにしました。

参考にさせてもらったのはこちらです。
0埋めする方法として下記のように記されていました。
--0埋めを行う(例、10桁)

SELECT
RIGHT(REPLICATE('0', 10) + REPLACE(STR(@Number), ' ', ''), 10)

--結果: '0000000123'

なにやら関数だらけですが、ようは下記のような流れになっています。
まず REPLICATE('0', 10)。結果は "0000000000" になります。
これに STR(@Number) で数値を文字列化。このとき、STRの第2引数に値を入れないと自動的に空白の入った10桁の文字列ができます。@Numberが"3"だとすると結果は" 123"となります。
この空白の入った文字列から空白除去するために REPLACE 関数で空白を空文字に置換します。この結果は"123"となります。
"+"記号はSQL Serverでは文字列連結演算子なので、ここまでの結果は "0000000000123"となります。
最後に仕上げで RIGHT 関数で右から10桁切り取ります。
これでめでたく"0000000123"という結果が返るわけです。

さて、このコードを見た同僚はもっとシンプルにできるということで、下記のようなSQLを書いてくれました。

SELECT
RIGHT('0000000000' + LTRIM(STR(@Number)), 10)

ようは空白除去に LTRIM 関数を、そして0埋めよう文字列は最初から''で用意しておくというわけです。

この方法で、Hour"列と"Minute"列を0埋めあり文字列に直すSQLはこうなりました。

SELECT
RIGHT('00' + LTRIM(STR( Hour )), 2) + ':' + RIGHT('00' + LTRIM(STR( Minute )), 2) + ':00'

あとはこの形式(hh:mm:ss)に直した比較用変数で普通に比較できます。
例:

declare @Time DateTime
SET @Time='13:00:00'
 
SELECT *
FROM TABLE
WHERE RIGHT('00' + LTRIM(STR( Hour )), 2) + ':' + RIGHT('00' + LTRIM(STR( Minute )), 2) + ':00' > CONVERT(varchar, @Time, 108)


ちなみにこれはSQL Server専用です。
DBMSでの文字列操作関数の違いはこちらに丁寧にまとめられています。
これを見ると文字列の連結(結合)もDBMSによって随分仕様が違うんですね。。