SQL Server 2008R2に顧客と注文のテーブルがあります。どちらも顧客IDにインデックスがあります(id
と呼ばれます)。顧客テーブル内のすべての顧客に関する詳細と、最初の注文の詳細など、注文テーブルからの情報を返す必要があります。
私は現在、ordersテーブルのサブクエリでcustomersテーブルに結合したままにしており、サブクエリは注文について必要な情報を返します。例えば:
SELECT c.id
,c.country
,First_orders.product
,First_orders.order_id
FROM customers c
LEFT JOIN SELECT( id,
product
FROM (SELECT id
,product
,order_id
,ROW_NUMBER() OVER (PARTITION BY id ORDER BY Order_Date asc) as order_No
FROM orders) orders
WHERE Order_no = 1) First_Orders
ON c.id = First_orders.id
私はSQLにまったく慣れていないので、これを効率的に行っているかどうかを理解したいと思います。このようなかなりの数のサブクエリを1つの選択クエリでcustomersテーブルに結合することになり、実行に数十分かかる場合があります。
それで、私はこれを効率的に行っていますか、それとも改善できますか?たとえば、ordersテーブルのidのインデックスが役立つかどうかはわかりません。最初にサブクエリにあるものの一時テーブルを作成し、idの一意のインデックスを作成することでクエリを高速化できます。 SQLServerがid
が一意の列であることを認識し、顧客テーブルをこの一時テーブルに結合するための一時テーブル?私は通常、顧客テーブルと注文テーブルに100万行または200万行あります。
よろしくお願いします!
サブクエリの1つを削除して、もう少し効率的にすることができます。
SELECT c.id
,c.country
,First_orders.product
,First_orders.order_id
FROM customers c
LEFT JOIN (SELECT id
,product
,order_id
,ROW_NUMBER() OVER (PARTITION BY id ORDER BY Order_Date asc) as order_No
FROM orders) First_Orders
ON c.id = First_orders.id AND First_Orders.order_No = 1
上記のクエリでは、かっこを配置する場所に注意する必要があります。これは機能しないと思います。また、結果には製品が返されますが、ネストされたサブクエリには含まれません。
SQLを学んでいるだけの人にとって、クエリはかなり見栄えがします。
顧客のインデックスはクエリに使用される場合と使用されない場合があります。実行プランを確認する必要があります。 orders(id, order_date)
のインデックスは、row_number
関数に非常に効果的に使用できます。
1つのコメントはフィールドの命名についてです。フィールドorders.id
は顧客IDであってはなりません。 'orders.Customer_Id`のようになります。ネーミングシステムをテーブル間で一貫性を保つことは、将来的に役立ちます。
これを試してください...理解しやすいです
;WITH cte
AS (
SELECT id
,product
,order_id
,ROW_NUMBER() OVER (
PARTITION BY id ORDER BY Order_Date ASC
) AS order_No
FROM orders
)
SELECT c.id
,c.country
,c1.Product
,c1.order_id
FROM customers c
INNER JOIN cte c1 ON c.id = c1.id
WHERE c1.order_No = 1