1

テーブルにINT列があります。この列には日付が特殊な形式で格納されます。その列をDATE型に変換しようとしています。月末に例外を含むSQL Serverの数値を日付に変換する

例えば、'2016-03-14'20160314とします。

例外は、毎月の最後の日に、私たちは日を保存していません。 したがって'2016-03-31'の場合は201603を保存し、数字がless than 999999かどうかを判断する必要があります。見つからない場合は、月末または月の他の日を表します。これは、すべての数学式である

クエリ1:

はこれまでのところ、私はこのタスクを達成するために、2つのクエリを持っています。

declare @k int = 20160321 
--declare @k int = 201603 
select 
    IIF(@k < 999999 
     , EOMONTH(DATEFROMPARTS(@k /100, @k % 100, 1), 0) 
     , DATEFROMPARTS(@k /10000, (@k/100) % 100, @k % 100) 
    ) 

クエリ2: この1つは、文字列操作を使用しています。

declare @k int = 20160321 
--declare @k int = 201603 

select 
    IIF(@k < 999999 
     , EOMONTH(cast(LEFT(@k, 4) + '-' + RIGHT(@k, 2) + '-01' as date), 0) 
     , cast(LEFT(@k, 4) + '-' + RIGHT(LEFT(@k, 6), 2) + '-' + RIGHT(@k, 2) as date) 
    ) AS DateColumn 

WHERE節で変換式を行う必要があります。

SELECT K, Dt, Name -- and more fields 
FROM tbl 
WHERE IIF(K < 999999 
      , EOMONTH(DATEFROMPARTS(K /100, K % 100, 1), 0) 
      , DATEFROMPARTS(K /10000, (K/100) % 100, K % 100) 
     ) < GetDate() 

そしてperformance is important

質問:何かのようにこれを行うには良い方法はありますか?おそらく、SQL ServerがK列にあるクラスタードインデックスを使用できる方法です。

+0

@hvd彼はそうではありません。彼は月の最終日の日付を返すEOMONTH()関数を使用しています。 –

+0

@hvd - 私は彼が 'EOMONTH'関数を呼び出すことによってそれをカバーしていると思います。 –

+0

はい、みんな。私がやったことに非常によく似たいくつかの方法があるかもしれません。その獣の事例はSQL ServerがK列にあるクラスタ化インデックスを使用できるようにするためのものです。これを問題の本文に追加します。 – FLICKER

答えて

1

クエリ1の方がパフォーマンスが良いと思いますが、確かめるためにはテストする必要があります。どのような種類のパフォーマンスがdatefromparts()datetimefromparts()であるかわかりません。彼らは比較的新しいので、正当な理由で魔法のように恐ろしいものだったら、私に衝撃を与えません。あなたは、文字列操作と型キャストのパフォーマンスと、算術と型キャストのパフォーマンスを比較しています。私の推測では、ほとんど洗濯ですが、その算術はおそらくより高速です。

パフォーマンス上の問題を解決するためのオプションは次のとおりです。a)テーブルにdatetime列を追加します。 b)計算された列をテーブルに追加します。 PERSISTED列を作成した場合は、列に索引を作成することもできます。 c)ビューを作成します(要件フープをジャンプすることができる場合はインデックス付きビュー)。 d)datetimeフィールドを持つ新しいテーブルを作成し、更新します。

(a)と(d)の両方がデータを複製するため、最初に表示されるほどのソリューションではありません。

私はいつも計算された列が少し粗いと判断しましたが、十分に機能します。ビューを作成する場合は、それを使用するためにINNER JOINに戻す必要がありますが、ほとんどのシステムではJOINSは非常に高速です。

私はおそらく、永続化された計算列またはビューを作成します。もちろん、最善の解決策は、最初に整数を日付として保存しないことです。


あなたはこのクエリを試みる場合があります:これはうまくいくかもしれない

SELECT CASE 
     WHEN @K < 999999 THEN EOMONTH(TRY_CONVERT(date, CAST(@K * 100 + 1 AS VARCHAR(10)))) 
     ELSE TRY_CONVERT(date, CAST(@K AS VARCHAR(10))) 
    END AS K_Date 

理由は、YYYYMMDDは、ISO日付フォーマットの一つであるということです。クエリエンジンはをすべて評価することができ、CASEの条件付きでエラーをスローすることなく、TRY_CONVERT()CONVERT()の前に試してみます。

+0

ありがとう@Bacon。だからあなたは私が実装したものとは異なる他の式/クエリを知らないのですか? – FLICKER

+0

@FLICKERああ、そうです。私の更新を参照してください。 –

+0

私はこれを試し、どのように実行するか見てみましょう。 – FLICKER

関連する問題