次のフィールドを含むOrdersというテーブルがあります:CustomerID、OrderDate
例えば
1, 01/01/2011
2, 02/02/2011
1, 01/07/2012
このテーブルをクエリして、顧客が2011年に注文し、2012年に何も注文していないかどうかを理解し、個別の顧客IDを返送する方法を見つけようとしています...
次の 2 つの方法を比較して、どちらの OrderDates が 2012 年からのものかを判断します。
Year(OrderDate) = 2012
OrderDate >= #2012-01-01# AND OrderDate < #2013-01-01#
最初のアプローチは、記述が簡単で理解しやすいものです。ただし、dbエンジンがOrders
テーブルのすべての行にアクセスし、そのYear()
関数を使用して行が基準を満たしているかどうかを確認する必要があります。テーブルが大きい場合や、ターゲット範囲外の OrderDates を持つ行が多数含まれている場合、これには多くの時間がかかる可能性があります。最も重要なことは、その関数は db エンジンにすべての行を強制的に検査させるため、クエリでインデックスを使用してデータ取得を高速化することができないということです。
2 番目のアプローチは、より冗長ではありますが、db エンジンが基準を満たす行のみを検査できるようにします。のインデックスを使用するOrderDate
と、最初のアプローチよりも簡単に 1 桁速くなる可能性があります。
テーブルが十分に小さい場合、および/またはパフォーマンスを気にしない場合、それは問題になりません。ただし、このバージョンを試すことをお勧めします...
SELECT DISTINCT o2011.CustomerID
FROM
Orders AS o2011
LEFT JOIN
(
SELECT DISTINCT CustomerID
FROM Orders
WHERE
OrderDate >= #2012-01-01#
AND OrderDate < #2013-01-01#
) AS sub2012
ON o2011.CustomerID = sub2012.CustomerID
WHERE
o2011.OrderDate >= #2011-01-01#
AND o2011.OrderDate < #2012-01-01#
AND sub2012.CustomerID Is Null;
これを試すことができます:
select distinct CustomerID
from Orders
where year(OrderDate) = 2011
and CustomerID not in (
select distinct CustomerID
from Orders
where year(OrderDate) = 2012
)