sql >> データベース >  >> RDS >> Sqlserver

SQL Server BETWEEN

    テーブルで BETWEEN をそのまま使用する方法を考え出すとうまくいきますが、すべての場合でパフォーマンスが低下します:

    • 行を日付として処理するのではなく、行に対して何らかの計算を行うために、せいぜいより多くの CPU を消費します。
    • 最悪の場合、テーブル内のすべての行でテーブル スキャンが強制されますが、列にインデックスがある場合は、適切なクエリでシークが可能です。制約を BETWEEN 句に強制するとインデックスの使用が無効になるため、これは大きなパフォーマンスの違いになる可能性があります。

    日付列にインデックスがあり、パフォーマンスを気にする場合は、代わりに次のことをお勧めします:

    DECLARE
       @FromDate date = '20111101',
       @ToDate date = '20120201';
    
    SELECT *
    FROM dbo.YourTable T
    WHERE
       (
          T.[Year] > Year(@FromDate)
          OR (    
             T.[Year] = Year(@FromDate)
             AND T.[Month] >= Month(@FromDate)
          )
       ) AND (
          T.[Year] < Year(@ToDate)
          OR (
             T.[Year] = Year(@ToDate)
             AND T.[Month] <= Month(@ToDate)
          )
       );
    

    ただし、このような構造は非常に扱いにくいため、使用したくないことは理解できます。したがって、少なくとも数値計算を使用し、日付から文字列への変換計算よりも少ない CPU を使用する妥協的なクエリを次に示します (ただし、実際のパフォーマンスの問題である強制スキャンを補うほどではありません)。

    SELECT *
    FROM dbo.YourTable T
    WHERE
       T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202;
    

    Year のインデックスがある場合 、次のようにクエリを送信することで大きな後押しを得ることができます。これにより、検索する機会があります:

    SELECT *
    FROM dbo.YourTable T
    WHERE
       T.[Year] * 100 + T.[Month] BETWEEN 201111 AND 201202
       AND T.[Year] BETWEEN 2011 AND 2012; -- allows use of an index on [Year]
    

    これは、単一の BETWEEN を使用するという要件を破りますが、 式、それはそれほど苦痛ではなく、Year で非常にうまく機能します

    テーブルを変更することもできます。率直に言って、日付データ型の単一の列ではなく、日付部分に個別の数値を使用するのは良くありません。良くない理由は、あなたが今直面している正確な問題のためです.--クエリを実行するのは非常に困難です.

    バイト数の節約が重要なデータ ウェアハウジングのシナリオでは、日付を数値として保存する状況を想定できます (201111 など)。 )しかし、それはお勧めできません。 最高 解決策は、月と年の数値を分割するのではなく、日付を使用するようにテーブルを変更することです。月全体を表すことを認識して、月の最初の日を保存するだけです。

    これらの列の使用方法を変更することはできないが、テーブルを変更できる場合は、永続化された計算列を追加できます:

    ALTER Table dbo.YourTable
       ADD ActualDate AS (DateAdd(year, [Year] - 1900, DateAdd(month, [Month], '18991201')))
       PERSISTED;
    

    これで、次のことができます:

    SELECT *
    FROM dbo.YourTable
    WHERE
       ActualDate BETWEEN '20111101' AND '20120201';
    

    PERSISTED キーワードは、スキャンは取得されますが、INSERT または UPDATE ごとに式が計算され、行に格納されるため、各行で計算を行う必要がないことを意味します。しかし、あなたはできます この列にインデックスを追加すると、シークが得られます。これにより、パフォーマンスが非常に向上します (ただし、全体として、これは実際の日付列を使用するように変更するほど理想的ではありません。より多くのスペースが必要になり、INSERT に影響を与えるためです)。および更新):

    CREATE NONCLUSTERED INDEX IX_YourTable_ActualDate ON dbo.YourTable (ActualDate);
    

    要約:テーブルをまったく変更できない場合は、何らかの方法で妥協する必要があります。日付が別々の列に分割されて保存されている場合、適切に機能する必要な単純な構文を取得することはできません。



    1. mysqlのエラーメッセージに新しい言語を追加するにはどうすればよいですか?

    2. 条件によるグループ化と精度を使用してMySqlからパーセンテージを取得する

    3. SQLクエリを使用したコンマ区切り値

    4. PHPのPDOを使用してmysqlデータベースにデータを挿入したい。しかし、データは挿入されません