1

私のdbaseには、intデータ型( '734503' = 01/01/2012)の6桁の日付形式があります。私はこれらをcharに正常に変換することができました:

SELECT CONVERT(char(12),dateadd(dd,(date_paid -    639906),'1/1/1753'),101)  
FROM   vouchers       
WHERE date_paid =    '734503'

これにより、2012年1月1日の出力が得られます。しかし、次のようなクエリで変換された日付を検索すると、次のようになります。

SELECT CONVERT(char(12),dateadd(dd,(date_paid - 639906),'1/1/1753'),101) 
FROM vouchers    
WHERE date_paid >= '09/01/2012'  AND date_paid <= '09/30/2012'

なぜ変換が行われないのですか?date_paidフィールドのWHEREステートメントでCONVERTを使用しても、そこで機能するべきではありませんか?

私の質問は、変換された文字の日付で検索し、6桁の日付を使用する必要がない方法だと思います。

4

2 に答える 2

1

問題は、INT列をSTRING値と比較していて、日付を比較しているかのように解決されることを期待していることです...

WHERE date_paid >= '09/01/2012'
  AND date_paid <= '09/30/2012' 

-- date_paid is an INT (according to your question)
-- '09/01/2012' is a STRING

データ型が異なるため、そこには暗黙のCAST()があります。事実上あなたはやっています...

WHERE CAST(date_paid AS VARCHAR(10)) >= '09/01/2012'
  AND CAST(date_paid AS VARCHAR(10)) <= '09/30/2012' 

-- NOTE:  All of these values are now strings
--        They may LOOK like dates, but they're just strings

実際に行う必要があるのは、文字列を整数に明示的に操作することです。

WHERE date_paid >= DATEDIFF(DAY, '01/01/1753', '09/01/2012') + 639906
  AND date_paid <= DATEDIFF(DAY, '01/01/1753', '09/30/2012') + 639906

これにも暗黙のキャストが含まれます。DATEDIFF()はDATETIMEデータ型のみを受け取るため、文字列は最初に暗黙的にDATETIMEにキャストされます。

編集:

もう1つのオプションは、date_paidフィールドをDateTimeにCAST()してから、それに基づいてWHERE計算を行うことです。ここでの欠点は
...-CAST()をすべての行で実行してから、WHERE句を適用
する必要があります-これにより、インデックスの使用が防止され、パフォーマンスが大幅に低下します

上記の答えは、定数値に対するすべての操作を実行するため、検索されたフィールドをネイティブ状態で処理できます。したがって、インデックスの使用が可能になります。

于 2012-10-19T15:32:05.607 に答える
1

まず、可能であれば、データベーススキーマを変更します。date_paid列のデータ型は、「int」または「char」ではなく、 datetimeまたはである必要があります。date

...しかし、このスキーマに固執している場合は、date_paid値が整数であるように見えます。ここで、693596の値はを表し1 jan 1900ます。(この日付は、SQL Serverのゼロ値がマップされる場所です。)したがって、必要なのは、検索値をこの量だけシフトまたはオフセットすることです。

検索する日付が今日、2012年10月19日であると想定します

 Declare @SearchDate DateTime = '20 Oct 2012'

次に、クエリ述語を次のように記述します。

  Select * From vouchers
  Where date_paid = DateDiff(day, 0, @searchDate) + 693596 

すべての処理または計算が列の等号の反対側で実行されるように、クエリを構造化してください(私の例が示すように)。date_paidこのようにして、クエリプロセッサはインデックスdate_Paidが存在する場合にそのインデックスを使用できます。クエリに関数呼び出しまたはその他の計算が含まれている場合、クエリはdate_Paidテーブル全体を読み取る必要があり、他の方法で使用可能なインデックスを使用することはできません。SARGableを参照してください。

ちなみに、このデザイン(日付を表すためにこの大きな整数が使用されている場所)がどこから来たのか正確に知りたいと思いました。この値が1900 * 365に正確に等しいことに気付きました。つまり、このスキームでは、ゼロ値は、ゼロ(キリストが生まれたとき)の1月1日を表します。これは、SQL Serverの日付で使用できないことを除いて、クールです。SQLServerの値は、日付を16ビットの符号付き整数として表します。これはゼロをマップします。 1900年1月1日までで、16ビット整数(-16,384)の最小値に制限されます。これは、1753年頃のある日付に相当します。

于 2012-10-19T15:40:15.407 に答える