0

部分的な日付 (2 つの日付の差) を HH:MM 形式でフォーマットしたいと考えています。

そのために、次のロジックを組み立てました。

LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' || LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00'))

このロジックをいくつかの間隔に適用する必要があるため、関数を使用して DRY にキーを設定するとよいでしょう。

Oracle 関数の作成に頼らずに、このロジックを (おそらく Java を使用して) SQL ステートメントに埋め込む方法はありますか?

** 編集 **

DATE_DIFFERENCE は負の値で、24 時間を超える場合があります。負の場合は符号を含めたいと思いますが、DATE_DIFFERENCE が 24 時間を超えている場合でも、時間と分の差を表します。

4

1 に答える 1

2

クエリからアクセスできる Java 関数は、SQL 関数よりもかなり手間がかかるため、何を意味しているのか完全にはわかりません。SQL コンテキストと PL/SQL コンテキストが混在するため、クエリを使用して関数を宣言することはできません。

あなたの変換は不必要に複雑に見えます。あなたはこれを行うことができます:

substr(numtodsinterval(date_difference, 'DAY'), 12, 5)

numtodsinterval関数は日付の差を取り、それを間隔データ型に変換しsubstr、時間と分をカバーするセクションを取得します。

ただし、分を丸めるのではなく切り捨てるため、動作が少し異なります。

with tmp as (
    select to_date('2013-04-11 13:17:15', 'YYYY-MM-DD HH24:MI:SS')
        - to_date('2013-04-11 12:57:38', 'YYYY-MM-DD HH24:MI:SS')
        as date_difference
    from dual
    union all
    select to_date('2013-04-11 11:11:35', 'YYYY-MM-DD HH24:MI:SS')
        - to_date('2013-04-10 22:40:45', 'YYYY-MM-DD HH24:MI:SS') 
    from dual
    union all
    select to_date('2013-04-11 00:59:59', 'YYYY-MM-DD HH24:MI:SS')
        - to_date('2013-04-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS') 
    from dual
)
select LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' ||
        LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00')),
    substr(numtodsinterval(date_difference, 'DAY'), 12, 5)
from tmp;

LTRIM(T SUBSTR(NUMTODSINTERV
------- --------------------
00:20   00:19
12:31   12:30
00:00   00:59

それらの完全な間隔は次のとおりです。

NUMTODSINTERVAL(DATE_DIFFERENCE,'DAY')
---------------------------------------------------------------------------
+000000000 00:19:37.000000000
+000000000 12:30:50.000000000
+000000000 00:59:59.000000000

したがって、明らかに最初のものは に丸められます00:20が、 に切り捨てられ00:19ます。Egor Skriptunoff がコメントで指摘したように、3 番目の計算では間違った答えが返されるため、今それを含めました。

これは分を丸めますが、少し長くなります:

to_char(round(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI')

私が使用したリテラルで使用される実際の日付は問題ではありません。それはいつでもかまいません。たとえば、代わりにdate '2001-01-01'使用できます。違いをオブジェクトにtrunc(sysdate)戻すだけで、その上で組み込み関数を使用できます。比較のために:DATEround(date)

with tmp as (...)
select LTRIM(TO_CHAR(TRUNC((DATE_DIFFERENCE) * 24),'00')) || ':' ||
        LTRIM(TO_CHAR(MOD(ROUND((DATE_DIFFERENCE)*24*60),60),'00')),
    substr(numtodsinterval(date_difference, 'DAY'), 12, 5),
    to_char(trunc(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI'),
    to_char(round(date '2001-01-01' + date_difference, 'MI'), 'HH24:MI')
from tmp;

LTRIM(T SUBSTR(NUMTODSINTERV TO_CH TO_CH
------- -------------------- ----- -----
00:20   00:19                00:19 00:20
12:31   12:30                12:30 12:31
00:00   00:59                00:59 01:00

アドホック関数が埋め込まれているなど、実際に必要なものはありませんが、少なくともロジックが明確であれば、再利用することはそれほど心配ではないかもしれません。ただし、SQL関数でラップすることは、まだひどいオプションではないかもしれません.

于 2013-04-16T13:16:10.170 に答える