スキャンの代わりにシークが可能です:
SELECT *
FROM Periods
WHERE
PeriodYear BETWEEN Year(@startdate) AND Year(@enddate)
AND PeriodYear * 4 + PeriodQuarter
BETWEEN Year(@startdate) * 4 + DATEPART(Quarter, @startdate)
AND Year(@startdate) * 4 + DATEPART(Quarter, @enddate)
説明:
年と四半期の 2 つの構成要素から新しいスケーリングされた整数を作成し、年と四半期の各組み合わせを 1 つの数値として扱います。
代わりに、次のようにしたと想像してください。
AND PeriodYear + (PeriodQuarter - 1) / 4.0
BETWEEN Year(@startdate) + (DATEPART(Quarter, @startdate) - 1) / 4.0
AND Year(@startdate) + (DATEPART(Quarter, @enddate) - 1) / 4.0
元の表現を「Mult」と呼び、この新しい表現を「Div」と呼んでいます。年と四半期、およびこれらの表現が評価されるものを次に示します。
年 四半期 Div Mult
2009 1 2009.00 8037
2009 2 2009.25 8038
2009 3 2009.50 8039
2009 4 2009.75 8040
2010 1 2010.00 8041
2010 2 2010.25 8042
2010 3 2010.50 8043
したがって、これらの行に対して WHERE 句を実行すると、次のようになります。
WHERE Div BETWEEN 2009.25 AND 2010.00
正しい行がどのように返されるかがわかります。Mult バージョンは実際にはまったく同じことを行い、四半期を縮小する代わりに年を拡大するだけです。私がそれを使用した理由は、整数の計算と乗算が分数の計算と除算よりも高速だからです。
年だけで始まる 2 つの条件を使用する理由は、クエリを検索可能にするためです。年だけに基づいてシークを実行したいのですが、これは、年に 4 を掛けたり、他の計算を行ったりする場合には不可能です。そのため、最初に適切な年だけをスキャンしてから、微調整して、結果に含まれない四半期を除外します。
もう 1 つのオプションは、計算列を追加してインデックスを配置することです。これにより、コードの挿入または更新を変更する必要はありませんが (列リストを適切に使用している限り)、必要に応じて通常の範囲計算を行うことができます。