300k行は巨大なテーブルではありません。 3億行のテーブルが頻繁に見られます。
クエリの最大の問題は、相関サブクエリを使用しているため、行ごとにサブクエリを再実行する必要があることです。 外側のクエリで。
多くの場合、すべてを実行する必要はありません。 1つのSQLステートメントでの作業。それをいくつかのより単純なSQLステートメントに分割することには利点があります:
- コーディングが簡単です。
- 最適化が容易です。
- デバッグが簡単です。
- 読みやすい。
- 新しい要件を実装する必要がある場合、またはいつ実装する必要がある場合でも、保守が容易になります。
購入数
SELECT customer, COUNT(sale) AS number_of_purchases
FROM sales
GROUP BY customer;
このクエリには、sales(customer、sale)のインデックスが最適です。
最終購入額
これは
SELECT a.customer, a.sale as max_sale
FROM sales a
LEFT OUTER JOIN sales b
ON a.customer=b.customer AND a.dates < b.dates
WHERE b.customer IS NULL;
つまり、行a
を一致させてください 架空の行にb
同じ顧客とより大きな日付があります。そのような行が見つからない場合は、a
その顧客にとって最大の日付が必要です。
このクエリには、sales(customer、dates、sale)のインデックスが最適です。
その最大の日に顧客に対して複数の販売がある可能性がある場合、このクエリは顧客ごとに複数の行を返します。ネクタイを壊すには、別の列を見つける必要があります。自動インクリメントの主キーを使用する場合は、一意であることが保証されており、時系列で増加する傾向があるため、タイブレーカーとして適しています。
SELECT a.customer, a.sale as max_sale
FROM sales a
LEFT OUTER JOIN sales b
ON a.customer=b.customer AND (a.dates < b.dates OR a.dates = b.dates and a.id < b.id)
WHERE b.customer IS NULL;
正の値の場合の購入総額
SELECT customer, SUM(sale) AS total_purchases
FROM sales
WHERE sale > 0
GROUP BY customer;
このクエリには、sales(customer、sale)のインデックスが最適です。
-1の代わりにNULLを使用して、不足している販売値を示すことを検討する必要があります。 SUM()やCOUNT()などの集計関数はNULLを無視するため、sale<0の行を除外するためにWHERE句を使用する必要はありません。
Re:コメント
2012年第4四半期の上位5社
SELECT customer, SUM(sale) AS total_purchases
FROM sales
WHERE (year, quarter) = (2012, 4) AND sale > 0
GROUP BY customer
ORDER BY total_purchases DESC
LIMIT 5;
実際のデータに対してテストしたいのですが、このクエリには売上(年、四半期、顧客、売上)のインデックスが最適だと思います。
合計購入数が5を超える顧客の最終購入
SELECT a.customer, a.sale as max_sale
FROM sales a
INNER JOIN sales c ON a.customer=c.customer
LEFT OUTER JOIN sales b
ON a.customer=b.customer AND (a.dates < b.dates OR a.dates = b.dates and a.id < b.id)
WHERE b.customer IS NULL
GROUP BY a.id
HAVING COUNT(*) > 5;
上記の他の最大のグループごとのクエリと同様に、sales(customer、dates、sale)のインデックスがこのクエリに最適です。おそらく、joinとgroup byの両方を最適化できないため、一時的なテーブルが発生します。ただし、少なくとも、一時テーブルは多数ではなく1つしか実行されません。
これらのクエリは十分に複雑です。 すべてを与えることができる単一のSQLクエリを作成しようとしないでください。 これらの結果の。ブライアン・カーニハンからの古典的な引用を覚えておいてください: