0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQLで「秒」を「hh:mm:ss」に変換するときにやらかした話

0
Posted at

概要

SQLで「秒」を hh:mm:ss 形式に変換する処理を書いたときに、
一見正しそうなのに結果がおかしくなるミスをやらかしたので備忘録として残します。


要件

あるテーブルに「経過時間(秒)」が数値で入っており、
それを VIEW 用に hh:mm:ss 形式へ変換する必要がありました。

要件まとめ

  • 入力:経過時間(秒)
  • 出力形式:hh:mm:ss
  • 0埋めする(00:00:00
  • 出力型:varchar

データ例

変換前

列名
経過時間 decimal(10,0) 43154

変換後(期待値)

列名
経過時間 varchar 11:59:14

やらかしたSQL

SELECT文の一部を抜粋します。

RIGHT('0' + CAST([経過時間] / 3600 AS VARCHAR), 2) + ':' 
+ RIGHT('0' + CAST(([経過時間] % 3600) / 60 AS VARCHAR), 2) + ':' 
+ RIGHT('0' + CAST([経過時間] % 60 AS VARCHAR), 2)

実行結果
22:33:14

🙃
全然違う。

原因

原因は decimal 型のまま割り算・剰余演算をしていたことでした。

  • 経過時間 の型:decimal(10,0)

  • SQL Server では

    • decimal / int
    • decimal % int

    の計算結果も decimal になる

その結果、意図しない計算結果になっていました。

つまり、

見た目は整数っぽいが、内部的には decimal のまま計算されていた

のが原因でした。


正しいSQL

bigint明示的にキャストしてから計算することで解決しました。

RIGHT('0' + CAST(CAST([経過時間] AS bigint) / 3600 AS VARCHAR), 2) + ':' 
+ RIGHT('0' + CAST((CAST([経過時間] AS bigint) % 3600) / 60 AS VARCHAR), 2) + ':' 
+ RIGHT('0' + CAST(CAST([経過時間] AS bigint) % 60 AS VARCHAR), 2) AS hms_time

教訓

  • 数値型は見た目だけで判断しない
  • decimal のまま計算すると、想定外の結果になることがある
  • 割り算や剰余演算は特に注意する
  • 意図した計算をしたい場合は、型を明示的にキャストする

追記

  • DATEADD関数は、経過時間が24時間以上の秒数には対応できない
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?