これを行うには多くの正しい方法があります。個別のEXISTS
顧客のリストが必要で、それ以外の注文からの詳細が少なくとも1つ存在しない場合は、半結合がPostgreSQLでおそらく最速です。
SELECT c.contactname, c.address
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customerid = c.customerid
AND o.orderdate >= '1997-1-1'::date
AND o.orderdate < '1998-1-1'::date
)
ORDER BY contactname;
なぜ使用するのですか?
WHERE o.orderdate >= '1997-1-1'::date
AND o.orderdate < '1998-1-1'::date
それ以外の:
WHERE date_part('year', orderdate) = 1997
式を使用すると、PostgreSQLは、条件をチェックする前に、すべての行の値を計算する必要があります。別の形式では、列は(そのままで)2つの定数項と照合されます。これにより、インデックスをより簡単に使用することもできます。より速くする必要があります。
クエリを読みやすくするためにテーブルエイリアスを使用する方法にも注意してください。
最初のクエリは、が原因で行の乗算に悩まされていJOIN
ます。customer
テーブル内の行にテーブル内の一致する行が複数ある場合、orders
注文ごとに1つの行を取得します。GROUP BY
あなたはそれを:で修正することができます
SELECT c.contactname, c.address
FROM customers c
JOIN orders o USING (customerid)
WHERE o.orderdate >= '1997-1-1'::date
AND o.orderdate < '1998-1-1'::date
GROUP BY c.customer_id --- or whatever is the primary key of c
ORDER BY c.contactname
..これは別の方法です。しかし、おそらくもっと遅いでしょう。テーブルから追加の(集約された)データも取得する場合は、このフォームを使用しますorders
。
DISTINCT
GROUP BY
この単純なケースではほとんど同じことを行うのに代わるものです。GROUP BY
この句を削除し、DISTINCT
後に追加しSELECT
ます。
2番目のクエリをで修正することもできますがDISTINCT
、最初の例を使用してください。