none
二つの日付の差を整数で求めるには? RRS feed

  • 質問

  • お世話になります. WinXP SP3, SQL Server 2005です.表題の件でご教示ください.

    DATEDIFF関数を使えばよいのは分かるのですが,使わずに求めるにはどうしたらよいですか?
    SELECT enddate - startdate
    とすると結果が小数で求まるので.日付を丸めるには?と言い換えた方が適切かもしれません.
    2009年8月6日 7:20

回答

  • こんにちは、nagino です。

    日付は型からして実装依存なので、なかなか難しいところですが、例えば以下のような手法があるかなと思います。

    ● 2009/8/6 23:00:00 から 2009/08/08 1:00:00 の間を 2 として計算したい(日単位に丸めてから、差を求めたい)場合
    FLOOR(enddate - '2000/01/01') - FLOOR(startdate - '2000/01/01')

    ● 2009/8/6 23:00:00 から 2009/08/08 1:00:00 の間を 1 として計算したい(差を求めてから、日単位に丸めたい)場合
    FLOOR(enddate - '2000/01/01')

    「-」による日付同士の演算では数値を返すようになっていたと思います。
    (ANSI 標準、SQL Server、Oracle、DB2、PostgreSQL、MySQL、Access のはず)

    また、「FLOOR」での切り捨ては ANSI 標準ではないのですが、多くの DB で実装されていたと思います。
    (SQL Server、Oracle、DB2、PostgreSQL、MySQL のはず)

    あと、各 DB では日付として処理できる範囲が異なりますが、2000/01/01 はいずれの DB でも日付として扱えたはずです。
    ・・・ただ、暗黙のキャストの挙動が異なると、期待通りに動かないかもしれません。
    CAST 自体は広く実装されていますが、引数で指定する型名が異なるので使えないと思うので、暗黙のキャストに頼るしかないかと。


    MCITP(Database Developer/Database Administrator)
    • 回答としてマーク じふ 2009年8月7日 2:02
    2009年8月6日 11:08
  • すみません.実装非依存のコードで書きたいだけです.

    実装非依存という言葉を見ての感想ですが、データベースによって基本的にSQLは微妙に異なりますし、できることも異なりますので、完全に実現するのは無理だと思います。早い話がSQLは各データベースの共通語ではないからです。例えば今回のご質問である日付の部分を仮に実装非依存にできたとしても、他の場所でできないところがでてくるのは、ほぼ確実でしょう。

    ちなみにSQL Serverでは、
    convert(smalldatetime, convert (nvarchar, getdate() , 111), 120)
    のようにすれば、日付の部分のみが取得できます。
    SQL Server 2008からは日付情報しか持たないDate型も導入されていますので、場合によっては便利に使用できると思います。

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク じふ 2009年8月7日 2:03
    2009年8月7日 0:24

すべての返信

  • こんにちは

    目的が良く分からないので、的外れかもしれませんが・・・

    「日付を丸めるには?」という点についてであれば、
    SELECT DAY(enddate - startdate) - 1
    みたいな感じで良いのでは?
    まあ、日数が1カ月以上あると上記ではだめですけど・・・

    2009年8月6日 7:39
  • お世話になります.

    > 目的が良く分からない

    すみません.実装非依存のコードで書きたいだけです.

    > SELECT DAY(enddate - startdate) - 1
    すみません,説明不足でした.

    例ですが,元の日付
    2009/8/6 17:50:00
    から
    2009/8/6 00:00:00
    を得たいという意味です.そのうえで
    SELECT '2009/8/6 00:00:00' - '2009/8/5 00:00:00'
    を得たいと.

    よろしくお願いします.

    2009年8月6日 8:52
  • こんにちは、nagino です。

    日付は型からして実装依存なので、なかなか難しいところですが、例えば以下のような手法があるかなと思います。

    ● 2009/8/6 23:00:00 から 2009/08/08 1:00:00 の間を 2 として計算したい(日単位に丸めてから、差を求めたい)場合
    FLOOR(enddate - '2000/01/01') - FLOOR(startdate - '2000/01/01')

    ● 2009/8/6 23:00:00 から 2009/08/08 1:00:00 の間を 1 として計算したい(差を求めてから、日単位に丸めたい)場合
    FLOOR(enddate - '2000/01/01')

    「-」による日付同士の演算では数値を返すようになっていたと思います。
    (ANSI 標準、SQL Server、Oracle、DB2、PostgreSQL、MySQL、Access のはず)

    また、「FLOOR」での切り捨ては ANSI 標準ではないのですが、多くの DB で実装されていたと思います。
    (SQL Server、Oracle、DB2、PostgreSQL、MySQL のはず)

    あと、各 DB では日付として処理できる範囲が異なりますが、2000/01/01 はいずれの DB でも日付として扱えたはずです。
    ・・・ただ、暗黙のキャストの挙動が異なると、期待通りに動かないかもしれません。
    CAST 自体は広く実装されていますが、引数で指定する型名が異なるので使えないと思うので、暗黙のキャストに頼るしかないかと。


    MCITP(Database Developer/Database Administrator)
    • 回答としてマーク じふ 2009年8月7日 2:02
    2009年8月6日 11:08
  • すみません.実装非依存のコードで書きたいだけです.

    実装非依存という言葉を見ての感想ですが、データベースによって基本的にSQLは微妙に異なりますし、できることも異なりますので、完全に実現するのは無理だと思います。早い話がSQLは各データベースの共通語ではないからです。例えば今回のご質問である日付の部分を仮に実装非依存にできたとしても、他の場所でできないところがでてくるのは、ほぼ確実でしょう。

    ちなみにSQL Serverでは、
    convert(smalldatetime, convert (nvarchar, getdate() , 111), 120)
    のようにすれば、日付の部分のみが取得できます。
    SQL Server 2008からは日付情報しか持たないDate型も導入されていますので、場合によっては便利に使用できると思います。

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク じふ 2009年8月7日 2:03
    2009年8月7日 0:24
  • お世話になります.

    > 日単位に丸めてから、差を求めたい
    今回の要望はこちらです.こちらで試したところ,明示的にDATETIME型,FLOAT型にキャストしてから計算しないと構文エラーとなりました.
    FLOOR関数やCEILING 関数はこうやって使うんですね...ありがとうございました.
    2009年8月7日 1:30
  • お世話になります.

    > 完全に実現するのは無理
    確かにそうかもしれません.できれば標準SQLで書きたかったんですが...完全には無理ということですね.ありがとうございました.
    2009年8月7日 1:35